@dataclouder/nest-vertex 0.0.56 → 0.0.58
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/comfyui/controllers/comfy-sdk.controller.js +12 -2
- package/comfyui/services/comfy-connection.service.js +4 -5
- package/comfyui/services/comfy-sdk.service.js +1 -1
- package/controllers/stt/adapter-stt.controller.d.ts +10 -0
- package/controllers/stt/adapter-stt.controller.js +79 -0
- package/controllers/stt/groq-stt.controller.js +1 -1
- package/controllers/stt/local-stt.controller.d.ts +8 -0
- package/controllers/stt/local-stt.controller.js +62 -0
- package/controllers/tts/vertex-gemini-tts.controller.js +1 -1
- package/controllers/tts/vertex-tts-adapter.controller.js +2 -2
- package/models/adapter.models.d.ts +1 -1
- package/models/key-balancer.models.d.ts +2 -0
- package/nest-vertex.module.js +7 -6
- package/package.json +1 -1
- package/services/vertex-gemini-chat.service.d.ts +1 -0
- package/services/vertex-gemini-chat.service.js +21 -14
- package/services/vertex-image.service.js +20 -16
- package/services/whisper/groq.service.js +1 -0
- package/services/whisper/local-stt.service.d.ts +7 -0
- package/services/whisper/local-stt.service.js +138 -0
- package/drizzle/drizzle.module.d.ts +0 -2
- package/drizzle/drizzle.module.js +0 -35
- package/drizzle/drizzle.service.d.ts +0 -10
- package/drizzle/drizzle.service.js +0 -68
- package/drizzle/dto/create-key-balancer.dto.d.ts +0 -9
- package/drizzle/dto/create-key-balancer.dto.js +0 -54
- package/drizzle/dto/create-key-usage.dto.d.ts +0 -6
- package/drizzle/dto/create-key-usage.dto.js +0 -11
- package/drizzle/dto/create-user-request.dto.d.ts +0 -7
- package/drizzle/dto/create-user-request.dto.js +0 -47
- package/drizzle/dto/update-key-balancer.dto.d.ts +0 -5
- package/drizzle/dto/update-key-balancer.dto.js +0 -9
- package/drizzle/dto/update-user-request.dto.d.ts +0 -5
- package/drizzle/dto/update-user-request.dto.js +0 -9
- package/drizzle/key-balancer.controller.d.ts +0 -13
- package/drizzle/key-balancer.controller.js +0 -103
- package/drizzle/key-balancer.model.d.ts +0 -10
- package/drizzle/key-balancer.model.js +0 -3
- package/drizzle/key-balancer.service.d.ts +0 -11
- package/drizzle/key-balancer.service.js +0 -50
- package/drizzle/key-usage.service.d.ts +0 -17
- package/drizzle/key-usage.service.js +0 -63
- package/drizzle/schema.d.ts +0 -395
- package/drizzle/schema.js +0 -33
- package/drizzle/user-requests.controller.d.ts +0 -47
- package/drizzle/user-requests.controller.js +0 -81
- package/drizzle/user-requests.service.d.ts +0 -47
- package/drizzle/user-requests.service.js +0 -47
- package/services/metric-ai.service.d.ts +0 -11
- package/services/metric-ai.service.js +0 -48
|
@@ -21,8 +21,18 @@ let ComfySDKController = class ComfySDKController {
|
|
|
21
21
|
return this.comfySDKService.testMethod();
|
|
22
22
|
}
|
|
23
23
|
async statusEndpoint() {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
try {
|
|
25
|
+
const status = await this.comfySDKService.getStatus();
|
|
26
|
+
return status;
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
const response = {
|
|
30
|
+
status: 'Server Down',
|
|
31
|
+
numAvailable: 0,
|
|
32
|
+
servers: [],
|
|
33
|
+
};
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
26
36
|
}
|
|
27
37
|
};
|
|
28
38
|
exports.ComfySDKController = ComfySDKController;
|
|
@@ -58,7 +58,6 @@ let ComfyConnectionService = ComfyConnectionService_1 = class ComfyConnectionSer
|
|
|
58
58
|
try {
|
|
59
59
|
await this.checkApiStatus();
|
|
60
60
|
this.logger.log('Successfully connected to ComfyUI server.');
|
|
61
|
-
this.connectWebSocket();
|
|
62
61
|
}
|
|
63
62
|
catch (error) {
|
|
64
63
|
this.logger.error('Failed to connect to ComfyUI server:', error.message || error);
|
|
@@ -109,7 +108,7 @@ let ComfyConnectionService = ComfyConnectionService_1 = class ComfyConnectionSer
|
|
|
109
108
|
this.logger.log('Disconnected from ComfyUI WebSocket. Attempting to reconnect...');
|
|
110
109
|
setTimeout(() => this.connectWebSocket(), 5000);
|
|
111
110
|
});
|
|
112
|
-
this.ws.on('error',
|
|
111
|
+
this.ws.on('error', error => {
|
|
113
112
|
this.logger.error('ComfyUI WebSocket error:', error);
|
|
114
113
|
});
|
|
115
114
|
}
|
|
@@ -177,7 +176,7 @@ let ComfyConnectionService = ComfyConnectionService_1 = class ComfyConnectionSer
|
|
|
177
176
|
prompt: workflow,
|
|
178
177
|
client_id: this.clientId,
|
|
179
178
|
};
|
|
180
|
-
return (0, rxjs_1.firstValueFrom)(this.httpService.post(url, payload)).then(
|
|
179
|
+
return (0, rxjs_1.firstValueFrom)(this.httpService.post(url, payload)).then(res => res.data);
|
|
181
180
|
}
|
|
182
181
|
async uploadImage(imageBuffer, filename) {
|
|
183
182
|
const url = `http://${this.comfyApiHost}/upload/image`;
|
|
@@ -198,11 +197,11 @@ let ComfyConnectionService = ComfyConnectionService_1 = class ComfyConnectionSer
|
|
|
198
197
|
reject(new Error(`Media generation timed out after ${timeoutMs / 1000} seconds for prompt ${prompt_id}.`));
|
|
199
198
|
}, timeoutMs);
|
|
200
199
|
this.pendingPrompts.set(prompt_id, {
|
|
201
|
-
resolve:
|
|
200
|
+
resolve: output => {
|
|
202
201
|
clearTimeout(timeout);
|
|
203
202
|
resolve(output);
|
|
204
203
|
},
|
|
205
|
-
reject:
|
|
204
|
+
reject: error => {
|
|
206
205
|
clearTimeout(timeout);
|
|
207
206
|
reject(error);
|
|
208
207
|
},
|
|
@@ -62,7 +62,7 @@ let ComfySDKService = ComfySDKService_1 = class ComfySDKService {
|
|
|
62
62
|
this.generatedAssetService = generatedAssetService;
|
|
63
63
|
this.httpService = httpService;
|
|
64
64
|
this.storageFactory = storageFactory;
|
|
65
|
-
this.api = new comfyui_sdk_1.ComfyApi('http://192.168.2.
|
|
65
|
+
this.api = new comfyui_sdk_1.ComfyApi(process.env.COMFYUI_API_HOST || 'http://192.168.2.2:8188').init();
|
|
66
66
|
console.log('what is in the comfy api?', this.api.apiHost);
|
|
67
67
|
}
|
|
68
68
|
init() {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type MulterFile } from '@webundsoehne/nest-fastify-file-upload';
|
|
2
|
+
import { GroqService } from '../../services/whisper/groq.service';
|
|
3
|
+
import { LocalSttService } from '../../services/whisper/local-stt.service';
|
|
4
|
+
export declare class AdapterSttController {
|
|
5
|
+
private readonly groqService;
|
|
6
|
+
private readonly localSttService;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(groqService: GroqService, localSttService: LocalSttService);
|
|
9
|
+
processAudio(file: MulterFile, provider?: 'local' | 'groq'): Promise<any>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var AdapterSttController_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.AdapterSttController = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const nest_fastify_file_upload_1 = require("@webundsoehne/nest-fastify-file-upload");
|
|
19
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
20
|
+
const nest_core_1 = require("@dataclouder/nest-core");
|
|
21
|
+
const groq_service_1 = require("../../services/whisper/groq.service");
|
|
22
|
+
const local_stt_service_1 = require("../../services/whisper/local-stt.service");
|
|
23
|
+
let AdapterSttController = AdapterSttController_1 = class AdapterSttController {
|
|
24
|
+
groqService;
|
|
25
|
+
localSttService;
|
|
26
|
+
logger = new common_1.Logger(AdapterSttController_1.name);
|
|
27
|
+
constructor(groqService, localSttService) {
|
|
28
|
+
this.groqService = groqService;
|
|
29
|
+
this.localSttService = localSttService;
|
|
30
|
+
}
|
|
31
|
+
async processAudio(file, provider = 'local') {
|
|
32
|
+
this.logger.log(`Receive request with provider: ${provider}`);
|
|
33
|
+
if (!file || !file.buffer) {
|
|
34
|
+
this.logger.error('No file buffer received.');
|
|
35
|
+
return { error: 'No file uploaded or file buffer is missing.' };
|
|
36
|
+
}
|
|
37
|
+
this.logger.log(`Received file: ${file.originalname}, mimetype: ${file.mimetype}, size: ${file.size}`);
|
|
38
|
+
try {
|
|
39
|
+
let result;
|
|
40
|
+
if (provider === 'groq') {
|
|
41
|
+
result = await this.groqService.transcribeAudio(file.buffer, file.originalname, file.mimetype);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
result = await this.localSttService.transcribeAudio(file.buffer, file.originalname, file.mimetype);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.logger.error('Error during transcription process:', error);
|
|
50
|
+
return { error: 'Failed to transcribe audio.', details: error.message };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
exports.AdapterSttController = AdapterSttController;
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, common_1.Post)('transcribe-bytes'),
|
|
57
|
+
(0, common_1.UseInterceptors)((0, nest_fastify_file_upload_1.FileInterceptor)('file')),
|
|
58
|
+
(0, swagger_1.ApiConsumes)('multipart/form-data'),
|
|
59
|
+
(0, nest_fastify_file_upload_1.ApiFileBody)('file'),
|
|
60
|
+
(0, swagger_1.ApiQuery)({
|
|
61
|
+
name: 'provider',
|
|
62
|
+
enum: ['local', 'groq'],
|
|
63
|
+
required: false,
|
|
64
|
+
description: 'The provider to use for transcription. Defaults to "local".',
|
|
65
|
+
}),
|
|
66
|
+
__param(0, (0, common_1.UploadedFile)('file')),
|
|
67
|
+
__param(1, (0, common_1.Query)('provider')),
|
|
68
|
+
__metadata("design:type", Function),
|
|
69
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
70
|
+
__metadata("design:returntype", Promise)
|
|
71
|
+
], AdapterSttController.prototype, "processAudio", null);
|
|
72
|
+
exports.AdapterSttController = AdapterSttController = AdapterSttController_1 = __decorate([
|
|
73
|
+
(0, swagger_1.ApiTags)('Speech-to-Text'),
|
|
74
|
+
(0, common_1.Controller)('api/ai-services/adapter/stt'),
|
|
75
|
+
(0, common_1.UseFilters)(nest_core_1.AllExceptionsHandler),
|
|
76
|
+
__metadata("design:paramtypes", [groq_service_1.GroqService,
|
|
77
|
+
local_stt_service_1.LocalSttService])
|
|
78
|
+
], AdapterSttController);
|
|
79
|
+
//# sourceMappingURL=adapter-stt.controller.js.map
|
|
@@ -55,7 +55,7 @@ __decorate([
|
|
|
55
55
|
], GroqSttController.prototype, "processAudio", null);
|
|
56
56
|
exports.GroqSttController = GroqSttController = GroqSttController_1 = __decorate([
|
|
57
57
|
(0, swagger_1.ApiTags)('Speech-to-Text'),
|
|
58
|
-
(0, common_1.Controller)('api/groq
|
|
58
|
+
(0, common_1.Controller)('api/ai-services/groq/stt'),
|
|
59
59
|
(0, common_1.UseFilters)(nest_core_1.AllExceptionsHandler),
|
|
60
60
|
__metadata("design:paramtypes", [groq_service_1.GroqService])
|
|
61
61
|
], GroqSttController);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type MulterFile } from '@webundsoehne/nest-fastify-file-upload';
|
|
2
|
+
import { LocalSttService } from '../../services/whisper/local-stt.service';
|
|
3
|
+
export declare class LocalSttController {
|
|
4
|
+
private readonly localSttService;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(localSttService: LocalSttService);
|
|
7
|
+
processAudio(file: MulterFile): Promise<any>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var LocalSttController_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.LocalSttController = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const nest_fastify_file_upload_1 = require("@webundsoehne/nest-fastify-file-upload");
|
|
19
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
20
|
+
const nest_core_1 = require("@dataclouder/nest-core");
|
|
21
|
+
const local_stt_service_1 = require("../../services/whisper/local-stt.service");
|
|
22
|
+
let LocalSttController = LocalSttController_1 = class LocalSttController {
|
|
23
|
+
localSttService;
|
|
24
|
+
logger = new common_1.Logger(LocalSttController_1.name);
|
|
25
|
+
constructor(localSttService) {
|
|
26
|
+
this.localSttService = localSttService;
|
|
27
|
+
}
|
|
28
|
+
async processAudio(file) {
|
|
29
|
+
this.logger.log('Receive requests');
|
|
30
|
+
if (!file || !file.buffer) {
|
|
31
|
+
this.logger.error('No file buffer received.');
|
|
32
|
+
return { error: 'No file uploaded or file buffer is missing.' };
|
|
33
|
+
}
|
|
34
|
+
this.logger.log(`Received file: ${file.originalname}, mimetype: ${file.mimetype}, size: ${file.size}`);
|
|
35
|
+
try {
|
|
36
|
+
const result = await this.localSttService.transcribeAudio(file.buffer, file.originalname, file.mimetype);
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
this.logger.error('Error during transcription process:', error);
|
|
41
|
+
return { error: 'Failed to transcribe audio.', details: error.message };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports.LocalSttController = LocalSttController;
|
|
46
|
+
__decorate([
|
|
47
|
+
(0, common_1.Post)('transcribe-bytes'),
|
|
48
|
+
(0, common_1.UseInterceptors)((0, nest_fastify_file_upload_1.FileInterceptor)('file')),
|
|
49
|
+
(0, swagger_1.ApiConsumes)('multipart/form-data'),
|
|
50
|
+
(0, nest_fastify_file_upload_1.ApiFileBody)('file'),
|
|
51
|
+
__param(0, (0, common_1.UploadedFile)('file')),
|
|
52
|
+
__metadata("design:type", Function),
|
|
53
|
+
__metadata("design:paramtypes", [Object]),
|
|
54
|
+
__metadata("design:returntype", Promise)
|
|
55
|
+
], LocalSttController.prototype, "processAudio", null);
|
|
56
|
+
exports.LocalSttController = LocalSttController = LocalSttController_1 = __decorate([
|
|
57
|
+
(0, swagger_1.ApiTags)('Speech-to-Text'),
|
|
58
|
+
(0, common_1.Controller)('api/ai-services/local/stt'),
|
|
59
|
+
(0, common_1.UseFilters)(nest_core_1.AllExceptionsHandler),
|
|
60
|
+
__metadata("design:paramtypes", [local_stt_service_1.LocalSttService])
|
|
61
|
+
], LocalSttController);
|
|
62
|
+
//# sourceMappingURL=local-stt.controller.js.map
|
|
@@ -79,7 +79,7 @@ __decorate([
|
|
|
79
79
|
__metadata("design:returntype", Promise)
|
|
80
80
|
], VertexGeminiTtsController.prototype, "synthesizeSpeech", null);
|
|
81
81
|
exports.VertexGeminiTtsController = VertexGeminiTtsController = __decorate([
|
|
82
|
-
(0, swagger_1.ApiTags)('
|
|
82
|
+
(0, swagger_1.ApiTags)('Text To Speech Gemini'),
|
|
83
83
|
(0, common_1.Controller)('api/vertex-gemini/tts'),
|
|
84
84
|
(0, common_1.UseFilters)(nest_core_1.AllExceptionsHandler),
|
|
85
85
|
__metadata("design:paramtypes", [vertex_gemini_tts_service_1.VertexGeminiTtsService])
|
|
@@ -104,8 +104,8 @@ __decorate([
|
|
|
104
104
|
__metadata("design:returntype", Promise)
|
|
105
105
|
], VertexTtsAdapterController.prototype, "listVoices", null);
|
|
106
106
|
exports.VertexTtsAdapterController = VertexTtsAdapterController = __decorate([
|
|
107
|
-
(0, swagger_1.ApiTags)('
|
|
108
|
-
(0, common_1.Controller)('api/
|
|
107
|
+
(0, swagger_1.ApiTags)('Text To Speech Adapter'),
|
|
108
|
+
(0, common_1.Controller)('api/ai-services/adapter/tts'),
|
|
109
109
|
(0, common_2.UseFilters)(nest_core_1.AllExceptionsHandler),
|
|
110
110
|
__metadata("design:paramtypes", [vertex_tts_service_1.VertextTtsService])
|
|
111
111
|
], VertexTtsAdapterController);
|
package/nest-vertex.module.js
CHANGED
|
@@ -36,15 +36,16 @@ const veo_video_controller_1 = require("./controllers/video/veo-video.controller
|
|
|
36
36
|
const google_genai_service_1 = require("./services/google-genai.service");
|
|
37
37
|
const groq_stt_controller_1 = require("./controllers/stt/groq-stt.controller");
|
|
38
38
|
const groq_service_1 = require("./services/whisper/groq.service");
|
|
39
|
+
const local_stt_controller_1 = require("./controllers/stt/local-stt.controller");
|
|
40
|
+
const local_stt_service_1 = require("./services/whisper/local-stt.service");
|
|
39
41
|
const comfy_sdk_service_1 = require("./comfyui/services/comfy-sdk.service");
|
|
40
42
|
const vertex_gemini_tts_controller_1 = require("./controllers/tts/vertex-gemini-tts.controller");
|
|
41
43
|
const vertex_gemini_tts_service_1 = require("./services/vertex-gemini-tts.service");
|
|
42
|
-
const drizzle_module_1 = require("./drizzle/drizzle.module");
|
|
43
44
|
const nest_auth_1 = require("@dataclouder/nest-auth");
|
|
44
|
-
const metric_ai_service_1 = require("./services/metric-ai.service");
|
|
45
45
|
const groq_llm_service_1 = require("./services/llm/groq-llm.service");
|
|
46
46
|
const groq_llm_controller_1 = require("./controllers/llm/groq-llm.controller");
|
|
47
47
|
const video_gen_adapter_controller_1 = require("./controllers/video/video-gen-adapter.controller");
|
|
48
|
+
const adapter_stt_controller_1 = require("./controllers/stt/adapter-stt.controller");
|
|
48
49
|
let NestVertexModule = class NestVertexModule {
|
|
49
50
|
};
|
|
50
51
|
exports.NestVertexModule = NestVertexModule;
|
|
@@ -56,7 +57,6 @@ exports.NestVertexModule = NestVertexModule = __decorate([
|
|
|
56
57
|
nest_mongo_1.DCMongoDBModule,
|
|
57
58
|
mongoose_1.MongooseModule.forFeature([{ name: generated_asset_entity_1.GeneratedAsset.name, schema: generated_asset_entity_1.GeneratedAssetSchema }]),
|
|
58
59
|
comfyui_module_1.ComfyUIModule,
|
|
59
|
-
drizzle_module_1.DrizzleModule,
|
|
60
60
|
nest_auth_1.NestAuthModule,
|
|
61
61
|
],
|
|
62
62
|
providers: [
|
|
@@ -74,9 +74,9 @@ exports.NestVertexModule = NestVertexModule = __decorate([
|
|
|
74
74
|
vertex_veo_genai_service_1.VertexVeoGenaiService,
|
|
75
75
|
google_genai_service_1.GoogleGenaiService,
|
|
76
76
|
groq_service_1.GroqService,
|
|
77
|
+
local_stt_service_1.LocalSttService,
|
|
77
78
|
comfy_sdk_service_1.ComfySDKService,
|
|
78
79
|
vertex_gemini_tts_service_1.VertexGeminiTtsService,
|
|
79
|
-
metric_ai_service_1.MetricAIService,
|
|
80
80
|
groq_llm_service_1.GroqLlmService,
|
|
81
81
|
],
|
|
82
82
|
exports: [
|
|
@@ -94,11 +94,10 @@ exports.NestVertexModule = NestVertexModule = __decorate([
|
|
|
94
94
|
vertex_veo_genai_service_1.VertexVeoGenaiService,
|
|
95
95
|
google_genai_service_1.GoogleGenaiService,
|
|
96
96
|
groq_service_1.GroqService,
|
|
97
|
+
local_stt_service_1.LocalSttService,
|
|
97
98
|
comfyui_module_1.ComfyUIModule,
|
|
98
99
|
comfy_sdk_service_1.ComfySDKService,
|
|
99
100
|
vertex_gemini_tts_service_1.VertexGeminiTtsService,
|
|
100
|
-
drizzle_module_1.DrizzleModule,
|
|
101
|
-
metric_ai_service_1.MetricAIService,
|
|
102
101
|
groq_llm_service_1.GroqLlmService,
|
|
103
102
|
],
|
|
104
103
|
controllers: [
|
|
@@ -112,7 +111,9 @@ exports.NestVertexModule = NestVertexModule = __decorate([
|
|
|
112
111
|
vertex_comfy_controller_1.VertexComfyController,
|
|
113
112
|
veo_video_controller_1.VertexVeoGenerationController,
|
|
114
113
|
groq_stt_controller_1.GroqSttController,
|
|
114
|
+
local_stt_controller_1.LocalSttController,
|
|
115
115
|
vertex_gemini_tts_controller_1.VertexGeminiTtsController,
|
|
116
|
+
adapter_stt_controller_1.AdapterSttController,
|
|
116
117
|
],
|
|
117
118
|
})
|
|
118
119
|
], NestVertexModule);
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ export declare class GeminiChatService {
|
|
|
15
15
|
chatStream(messages: MessageLLM[], model?: string, keyType?: TierType): Promise<AsyncIterable<ChatMessageDict>>;
|
|
16
16
|
listModels(): Promise<Record<string, string>[]>;
|
|
17
17
|
getDefaultQualityModel(quality: EModelQuality): string;
|
|
18
|
+
private getBestModel;
|
|
18
19
|
private _extractJsonWithRecovery;
|
|
19
20
|
chatAndExtractJson(messages: MessageLLM[], model?: string, keyType?: TierType): Promise<ChatJsonResponse>;
|
|
20
21
|
describeImageByUrl(dto: DescribeImageRequestAdapter): Promise<any>;
|
|
@@ -93,8 +93,8 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
|
|
|
93
93
|
this.logger.debug(`Received Gemini response text. ${response?.text.slice(0, 50).replace(/\n/g, '')} ...`);
|
|
94
94
|
const responseText = response?.text ?? '';
|
|
95
95
|
const tokens = {
|
|
96
|
-
input: response?.usageMetadata?.
|
|
97
|
-
output: response?.usageMetadata?.
|
|
96
|
+
input: response?.usageMetadata?.promptTokenCount,
|
|
97
|
+
output: response?.usageMetadata?.candidatesTokenCount,
|
|
98
98
|
total: response?.usageMetadata?.totalTokenCount,
|
|
99
99
|
};
|
|
100
100
|
return {
|
|
@@ -201,6 +201,19 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
|
|
|
201
201
|
return gemini_models_1.GeminiModels.Gemini2_5Pro;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
|
+
getBestModel(conversation) {
|
|
205
|
+
if (!conversation.model) {
|
|
206
|
+
return { provider: 'google', modelName: gemini_models_1.GeminiModels.Gemini2_5Lite };
|
|
207
|
+
}
|
|
208
|
+
const { quality, modelName, provider } = conversation.model;
|
|
209
|
+
if (quality) {
|
|
210
|
+
return { provider: 'google', modelName: this.getDefaultQualityModel(quality) };
|
|
211
|
+
}
|
|
212
|
+
if (modelName && provider) {
|
|
213
|
+
return { provider, modelName };
|
|
214
|
+
}
|
|
215
|
+
return { provider: 'google', modelName: gemini_models_1.GeminiModels.Gemini2_5Lite };
|
|
216
|
+
}
|
|
204
217
|
async _extractJsonWithRecovery(responseText, model, keyType) {
|
|
205
218
|
try {
|
|
206
219
|
const json = (0, llm_models_1.extractJsonFromResponse)(responseText);
|
|
@@ -286,36 +299,30 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
|
|
|
286
299
|
}
|
|
287
300
|
async chatWithConversation(conversation) {
|
|
288
301
|
const startTime = Date.now();
|
|
289
|
-
|
|
290
|
-
conversation.model = { provider: 'google', modelName: gemini_models_1.GeminiModels.Gemini2_5Lite, id: 'no-id' };
|
|
291
|
-
}
|
|
302
|
+
const { provider, modelName } = this.getBestModel(conversation);
|
|
292
303
|
const tierType = conversation.tierType || key_balancer_models_1.TierType.TIER_1;
|
|
293
|
-
if (conversation?.model?.quality) {
|
|
294
|
-
conversation.model.provider = 'google';
|
|
295
|
-
conversation.model.modelName = this.getDefaultQualityModel(conversation.model.quality);
|
|
296
|
-
}
|
|
297
304
|
const returnJson = conversation.returnJson;
|
|
298
305
|
if (returnJson) {
|
|
299
|
-
const obj = await this.chatAndExtractJson(conversation.messages,
|
|
306
|
+
const obj = await this.chatAndExtractJson(conversation.messages, modelName, tierType);
|
|
300
307
|
const endTime = Date.now();
|
|
301
308
|
const processTime = (endTime - startTime) / 1000;
|
|
302
309
|
const metadata = {
|
|
303
310
|
type: 'json',
|
|
304
|
-
provider
|
|
305
|
-
model:
|
|
311
|
+
provider,
|
|
312
|
+
model: modelName,
|
|
306
313
|
processTime,
|
|
307
314
|
...obj?.metadata,
|
|
308
315
|
};
|
|
309
316
|
return { content: obj.json, role: adapter_models_1.ChatRole.Assistant, metadata };
|
|
310
317
|
}
|
|
311
318
|
else {
|
|
312
|
-
const response = await this.chat(conversation.messages,
|
|
319
|
+
const response = await this.chat(conversation.messages, modelName, tierType);
|
|
313
320
|
const endTime = Date.now();
|
|
314
321
|
const processTime = (endTime - startTime) / 1000;
|
|
315
322
|
return {
|
|
316
323
|
content: response.content,
|
|
317
324
|
role: response.role,
|
|
318
|
-
metadata: { provider
|
|
325
|
+
metadata: { provider, model: modelName, processTime, tokens: response.metadata.tokens },
|
|
319
326
|
};
|
|
320
327
|
}
|
|
321
328
|
}
|
|
@@ -38,32 +38,36 @@ let ImageVertexService = ImageVertexService_1 = class ImageVertexService {
|
|
|
38
38
|
let apiKey;
|
|
39
39
|
let keyId;
|
|
40
40
|
let availableKey = {};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
keyId = 'local';
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
this.logger.log(`Vertex Image"Getting key for model: ${model} and tier: ${tierType}`);
|
|
41
|
+
try {
|
|
42
|
+
this.logger.log(`Vertex Image - Getting key for model: ${model} and tier: ${tierType}`);
|
|
47
43
|
availableKey = await this.keyBalancerApiService.getBestKey({
|
|
48
44
|
provider: 'google',
|
|
49
45
|
service: model,
|
|
50
46
|
tierType: tierType,
|
|
51
47
|
aiType: key_balancer_models_1.ModelType.IMAGE,
|
|
52
48
|
}, null);
|
|
53
|
-
if (availableKey
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
if (availableKey?.error === 'RateLimited') {
|
|
57
|
-
this.logger.error('No available API key from key balancer.');
|
|
58
|
-
throw new Error('RateLimited');
|
|
59
|
-
}
|
|
60
|
-
if (!availableKey || availableKey?.error) {
|
|
61
|
-
this.logger.error('No available API key from key balancer.');
|
|
62
|
-
throw new Error('Not available API key');
|
|
49
|
+
if (!availableKey || availableKey.error) {
|
|
50
|
+
throw new Error('No available API key from key balancer or error received.');
|
|
63
51
|
}
|
|
52
|
+
this.logger.log(` USING Balanced key 🖼️ ${availableKey.name} ${availableKey.id}`);
|
|
64
53
|
apiKey = availableKey.key;
|
|
65
54
|
keyId = availableKey.id;
|
|
66
55
|
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
this.logger.warn(`Failed to get key from KeyBalancer: ${error.message}. Falling back to GEMINI_API_KEY.`);
|
|
58
|
+
if (this.gemini_key) {
|
|
59
|
+
apiKey = this.gemini_key;
|
|
60
|
+
keyId = 'local-gemini-key';
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.logger.error('Fallback to GEMINI_API_KEY failed as it is not set.');
|
|
64
|
+
throw new Error('No available API key from KeyBalancer and no fallback GEMINI_API_KEY set.');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!apiKey) {
|
|
68
|
+
this.logger.error('Could not obtain an API key.');
|
|
69
|
+
throw new Error('Not available API key');
|
|
70
|
+
}
|
|
67
71
|
return {
|
|
68
72
|
client: new genai_1.GoogleGenAI({ apiKey }),
|
|
69
73
|
keyId,
|
|
@@ -113,6 +113,7 @@ let GroqService = GroqService_1 = class GroqService {
|
|
|
113
113
|
tierType: key_balancer_models_1.TierType.FREE_TIER,
|
|
114
114
|
aiType: key_balancer_models_1.ModelType.AUDIO,
|
|
115
115
|
}, null);
|
|
116
|
+
console.log(`Using key: ${keyResult.name} {${keyResult?.service}}`);
|
|
116
117
|
const transcription = await this.getClientWithKey(keyResult.key).audio.transcriptions.create({
|
|
117
118
|
file: file,
|
|
118
119
|
model: 'whisper-large-v3-turbo',
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
var LocalSttService_1;
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.LocalSttService = void 0;
|
|
47
|
+
const common_1 = require("@nestjs/common");
|
|
48
|
+
const openai_1 = __importStar(require("openai"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
let LocalSttService = LocalSttService_1 = class LocalSttService {
|
|
51
|
+
logger = new common_1.Logger(LocalSttService_1.name);
|
|
52
|
+
openai;
|
|
53
|
+
constructor() {
|
|
54
|
+
const aiServerHost = process.env.AI_LAB_HOST;
|
|
55
|
+
console.log('Connecting to host AI_LAB_HOST', aiServerHost);
|
|
56
|
+
this.openai = new openai_1.default({
|
|
57
|
+
baseURL: `${aiServerHost}:3171/v1`,
|
|
58
|
+
apiKey: '',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
getExtensionFromMimeType(mimeType) {
|
|
62
|
+
switch (mimeType?.toLowerCase()) {
|
|
63
|
+
case 'audio/wav':
|
|
64
|
+
case 'audio/x-wav':
|
|
65
|
+
return '.wav';
|
|
66
|
+
case 'audio/mpeg':
|
|
67
|
+
return '.mp3';
|
|
68
|
+
case 'audio/mp4':
|
|
69
|
+
case 'video/mp4':
|
|
70
|
+
return '.mp4';
|
|
71
|
+
case 'audio/flac':
|
|
72
|
+
return '.flac';
|
|
73
|
+
case 'audio/ogg':
|
|
74
|
+
return '.ogg';
|
|
75
|
+
case 'audio/opus':
|
|
76
|
+
return '.opus';
|
|
77
|
+
case 'audio/webm':
|
|
78
|
+
case 'video/webm':
|
|
79
|
+
return '.webm';
|
|
80
|
+
case 'audio/mpga':
|
|
81
|
+
return '.mpga';
|
|
82
|
+
case 'audio/m4a':
|
|
83
|
+
return '.m4a';
|
|
84
|
+
default:
|
|
85
|
+
this.logger.warn(`Unsupported or unknown mime type provided: ${mimeType}`);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async transcribeAudio(fileBuffer, originalFileName, mimeType) {
|
|
90
|
+
this.logger.log(`Attempting to transcribe file: ${originalFileName} (${mimeType})`);
|
|
91
|
+
const extension = this.getExtensionFromMimeType(mimeType);
|
|
92
|
+
let effectiveFileName = originalFileName;
|
|
93
|
+
if (extension) {
|
|
94
|
+
const currentExt = path.extname(originalFileName).toLowerCase();
|
|
95
|
+
if (currentExt !== extension) {
|
|
96
|
+
const baseName = path.basename(originalFileName, currentExt);
|
|
97
|
+
effectiveFileName = `${baseName}${extension}`;
|
|
98
|
+
this.logger.log(`Adjusted filename to: ${effectiveFileName} based on mime type: ${mimeType}`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this.logger.log(`Filename ${originalFileName} already has correct extension ${extension}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
this.logger.warn(`Could not determine valid extension for mime type ${mimeType}. Using original filename: ${originalFileName}. Transcription may fail if the filename lacks a supported extension.`);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
console.log(' -> Request to...', this.openai.baseURL);
|
|
109
|
+
const result = await this.openai.audio.transcriptions.create({
|
|
110
|
+
model: 'rtlingo/mobiuslabsgmbh-faster-whisper-large-v3-turbo',
|
|
111
|
+
file: await (0, openai_1.toFile)(fileBuffer, effectiveFileName, { type: mimeType }),
|
|
112
|
+
response_format: 'verbose_json',
|
|
113
|
+
timestamp_granularities: ['word'],
|
|
114
|
+
});
|
|
115
|
+
if (result?.segments) {
|
|
116
|
+
delete result.segments;
|
|
117
|
+
}
|
|
118
|
+
if (result?.words?.length) {
|
|
119
|
+
result.words.forEach((word) => {
|
|
120
|
+
delete word?.probability;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
this.logger.log(`Transcription successful for file: ${result.text}, lang: ${result.language}, duration: ${result.duration}`);
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
this.logger.error(`Error during transcription for file ${effectiveFileName}:`, error?.error || error);
|
|
128
|
+
const errorMessage = error?.error?.message || (error instanceof Error ? error.message : 'Unknown error during transcription');
|
|
129
|
+
throw new Error(`Failed to transcribe audio: ${errorMessage}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
exports.LocalSttService = LocalSttService;
|
|
134
|
+
exports.LocalSttService = LocalSttService = LocalSttService_1 = __decorate([
|
|
135
|
+
(0, common_1.Injectable)(),
|
|
136
|
+
__metadata("design:paramtypes", [])
|
|
137
|
+
], LocalSttService);
|
|
138
|
+
//# sourceMappingURL=local-stt.service.js.map
|