mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
Fixed the duplicate data check problem, history filter and add tts stream (#477)
This commit is contained in:
3
packages/global/core/ai/model.d.ts
vendored
3
packages/global/core/ai/model.d.ts
vendored
@@ -29,4 +29,7 @@ export type AudioSpeechModelType = {
|
||||
model: string;
|
||||
name: string;
|
||||
price: number;
|
||||
baseUrl?: string;
|
||||
key?: string;
|
||||
voices: { label: string; value: string; bufferId: string }[];
|
||||
};
|
||||
|
@@ -105,11 +105,14 @@ export const defaultAudioSpeechModels: AudioSpeechModelType[] = [
|
||||
{
|
||||
model: 'tts-1',
|
||||
name: 'OpenAI TTS1',
|
||||
price: 0
|
||||
},
|
||||
{
|
||||
model: 'tts-1-hd',
|
||||
name: 'OpenAI TTS1',
|
||||
price: 0
|
||||
price: 0,
|
||||
voices: [
|
||||
{ label: 'Alloy', value: 'Alloy', bufferId: 'openai-Alloy' },
|
||||
{ label: 'Echo', value: 'Echo', bufferId: 'openai-Echo' },
|
||||
{ label: 'Fable', value: 'Fable', bufferId: 'openai-Fable' },
|
||||
{ label: 'Onyx', value: 'Onyx', bufferId: 'openai-Onyx' },
|
||||
{ label: 'Nova', value: 'Nova', bufferId: 'openai-Nova' },
|
||||
{ label: 'Shimmer', value: 'Shimmer', bufferId: 'openai-Shimmer' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
8
packages/global/core/ai/speech/api.d.ts
vendored
8
packages/global/core/ai/speech/api.d.ts
vendored
@@ -1,8 +0,0 @@
|
||||
import { Text2SpeechVoiceEnum } from './constant';
|
||||
|
||||
export type Text2SpeechProps = {
|
||||
model?: string;
|
||||
voice?: `${Text2SpeechVoiceEnum}`;
|
||||
input: string;
|
||||
speed?: number;
|
||||
};
|
@@ -1,17 +0,0 @@
|
||||
export enum Text2SpeechVoiceEnum {
|
||||
alloy = 'alloy',
|
||||
echo = 'echo',
|
||||
fable = 'fable',
|
||||
onyx = 'onyx',
|
||||
nova = 'nova',
|
||||
shimmer = 'shimmer'
|
||||
}
|
||||
export const openaiTTSList = [
|
||||
Text2SpeechVoiceEnum.alloy,
|
||||
Text2SpeechVoiceEnum.echo,
|
||||
Text2SpeechVoiceEnum.fable,
|
||||
Text2SpeechVoiceEnum.onyx,
|
||||
Text2SpeechVoiceEnum.nova,
|
||||
Text2SpeechVoiceEnum.shimmer
|
||||
];
|
||||
export const openaiTTSModel = 'tts-1';
|
1
packages/global/core/app/type.d.ts
vendored
1
packages/global/core/app/type.d.ts
vendored
@@ -1,7 +1,6 @@
|
||||
import { ModuleItemType } from '../module/type';
|
||||
import { AppTypeEnum } from './constants';
|
||||
import { PermissionTypeEnum } from '../../support/permission/constant';
|
||||
import { Text2SpeechVoiceEnum } from '../ai/speech/constant';
|
||||
|
||||
export interface AppSchema {
|
||||
_id: string;
|
||||
|
3
packages/global/core/chat/type.d.ts
vendored
3
packages/global/core/chat/type.d.ts
vendored
@@ -39,7 +39,6 @@ export type ChatItemSchema = {
|
||||
userFeedback?: string;
|
||||
adminFeedback?: AdminFbkType;
|
||||
[TaskResponseKeyEnum.responseData]?: ChatHistoryItemResType[];
|
||||
tts?: Buffer;
|
||||
};
|
||||
|
||||
export type AdminFbkType = {
|
||||
@@ -62,7 +61,7 @@ export type ChatItemType = {
|
||||
export type ChatSiteItemType = {
|
||||
status: 'loading' | 'running' | 'finish';
|
||||
moduleName?: string;
|
||||
ttsBuffer?: Buffer;
|
||||
ttsBuffer?: Uint8Array;
|
||||
} & ChatItemType;
|
||||
|
||||
export type HistoryItemType = {
|
||||
|
35
packages/service/common/buffer/tts/schema.ts
Normal file
35
packages/service/common/buffer/tts/schema.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { connectionMongo, type Model } from '../../../common/mongo';
|
||||
const { Schema, model, models } = connectionMongo;
|
||||
import { TTSBufferSchemaType } from './type.d';
|
||||
|
||||
export const collectionName = 'ttsbuffers';
|
||||
|
||||
const TTSBufferSchema = new Schema({
|
||||
bufferId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
buffer: {
|
||||
type: Buffer,
|
||||
required: true
|
||||
},
|
||||
createTime: {
|
||||
type: Date,
|
||||
default: () => new Date()
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
TTSBufferSchema.index({ bufferId: 1 });
|
||||
// 24 hour
|
||||
TTSBufferSchema.index({ createTime: 1 }, { expireAfterSeconds: 24 * 60 * 60 });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
export const MongoTTSBuffer: Model<TTSBufferSchemaType> =
|
||||
models[collectionName] || model(collectionName, TTSBufferSchema);
|
5
packages/service/common/buffer/tts/type.d.ts
vendored
Normal file
5
packages/service/common/buffer/tts/type.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export type TTSBufferSchemaType = {
|
||||
bufferId: string;
|
||||
text: string;
|
||||
buffer: Buffer;
|
||||
};
|
@@ -1,26 +1,49 @@
|
||||
import { Text2SpeechProps } from '@fastgpt/global/core/ai/speech/api';
|
||||
import type { NextApiResponse } from 'next';
|
||||
import { getAIApi } from '../config';
|
||||
import { defaultAudioSpeechModels } from '../../../../global/core/ai/model';
|
||||
import { Text2SpeechVoiceEnum } from '@fastgpt/global/core/ai/speech/constant';
|
||||
import { UserModelSchema } from '@fastgpt/global/support/user/type';
|
||||
|
||||
export async function text2Speech({
|
||||
model = defaultAudioSpeechModels[0].model,
|
||||
voice = Text2SpeechVoiceEnum.alloy,
|
||||
res,
|
||||
onSuccess,
|
||||
onError,
|
||||
input,
|
||||
speed = 1
|
||||
}: Text2SpeechProps) {
|
||||
const ai = getAIApi();
|
||||
const mp3 = await ai.audio.speech.create({
|
||||
model = defaultAudioSpeechModels[0].model,
|
||||
voice,
|
||||
speed = 1,
|
||||
props
|
||||
}: {
|
||||
res: NextApiResponse;
|
||||
onSuccess: (e: { model: string; buffer: Buffer }) => void;
|
||||
onError: (e: any) => void;
|
||||
input: string;
|
||||
model: string;
|
||||
voice: string;
|
||||
speed?: number;
|
||||
props?: UserModelSchema['openaiAccount'];
|
||||
}) {
|
||||
const ai = getAIApi(props);
|
||||
const response = await ai.audio.speech.create({
|
||||
model,
|
||||
// @ts-ignore
|
||||
voice,
|
||||
input,
|
||||
response_format: 'mp3',
|
||||
speed
|
||||
});
|
||||
const buffer = Buffer.from(await mp3.arrayBuffer());
|
||||
return {
|
||||
model,
|
||||
voice,
|
||||
tts: buffer
|
||||
};
|
||||
|
||||
const readableStream = response.body as unknown as NodeJS.ReadableStream;
|
||||
readableStream.pipe(res);
|
||||
|
||||
let bufferStore = Buffer.from([]);
|
||||
|
||||
readableStream.on('data', (chunk) => {
|
||||
bufferStore = Buffer.concat([bufferStore, chunk]);
|
||||
});
|
||||
readableStream.on('end', () => {
|
||||
onSuccess({ model, buffer: bufferStore });
|
||||
});
|
||||
readableStream.on('error', (e) => {
|
||||
onError(e);
|
||||
});
|
||||
}
|
||||
|
@@ -68,9 +68,6 @@ const ChatItemSchema = new Schema({
|
||||
[TaskResponseKeyEnum.responseData]: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
tts: {
|
||||
type: Buffer
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user