@dataclouder/nest-vertex 0.0.7 → 0.0.8

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.
@@ -0,0 +1 @@
1
+ export declare function saveAudioToFile(audioBuffer: Buffer, filename: string): Promise<string | null>;
package/audio.utils.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveAudioToFile = saveAudioToFile;
4
+ const path = require("path");
5
+ const fs = require("fs/promises");
6
+ const common_1 = require("@nestjs/common");
7
+ const logger = new common_1.Logger('AudioUtils');
8
+ async function saveAudioToFile(audioBuffer, filename) {
9
+ const audioDir = path.join(process.cwd(), 'public', 'tts-audio');
10
+ const filePath = path.join(audioDir, filename);
11
+ try {
12
+ await fs.mkdir(audioDir, { recursive: true });
13
+ await fs.writeFile(filePath, audioBuffer);
14
+ logger.log(`Audio saved successfully to ${filePath}`);
15
+ return filePath;
16
+ }
17
+ catch (saveError) {
18
+ logger.error(`Failed to save audio file to ${filePath}: ${saveError.message}`, saveError.stack);
19
+ return null;
20
+ }
21
+ }
22
+ //# sourceMappingURL=audio.utils.js.map
@@ -6,6 +6,7 @@ export declare class NestVertexController {
6
6
  private readonly nestVertexService;
7
7
  private readonly logger;
8
8
  constructor(nestVertexService: NestVertexService);
9
+ listModels(): Promise<string[]>;
9
10
  generateVideo(generateVideoDto: GenerateVideoDto): Promise<{
10
11
  operationName: string;
11
12
  }>;
@@ -25,6 +25,9 @@ let NestVertexController = NestVertexController_1 = class NestVertexController {
25
25
  constructor(nestVertexService) {
26
26
  this.nestVertexService = nestVertexService;
27
27
  }
28
+ async listModels() {
29
+ return this.nestVertexService.listModels();
30
+ }
28
31
  async generateVideo(generateVideoDto) {
29
32
  this.logger.log(`Received request to generate video: ${JSON.stringify(generateVideoDto)}`);
30
33
  try {
@@ -59,6 +62,12 @@ let NestVertexController = NestVertexController_1 = class NestVertexController {
59
62
  }
60
63
  };
61
64
  exports.NestVertexController = NestVertexController;
65
+ __decorate([
66
+ (0, common_1.Get)('list-models'),
67
+ __metadata("design:type", Function),
68
+ __metadata("design:paramtypes", []),
69
+ __metadata("design:returntype", Promise)
70
+ ], NestVertexController.prototype, "listModels", null);
62
71
  __decorate([
63
72
  (0, common_1.Post)('generate-video'),
64
73
  __param(0, (0, common_1.Body)(new common_1.ValidationPipe({ transform: true, whitelist: true }))),
package/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export * from './controllers/nest-tts.controller';
3
3
  export * from './services/nest-vertex.service';
4
4
  export * from './services/nest-tts.service';
5
5
  export * from './services/gemini-chat.service';
6
+ export * from './services/vertex-image.service';
6
7
  export * from './dto/generate-image.dto';
package/index.js CHANGED
@@ -19,5 +19,6 @@ __exportStar(require("./controllers/nest-tts.controller"), exports);
19
19
  __exportStar(require("./services/nest-vertex.service"), exports);
20
20
  __exportStar(require("./services/nest-tts.service"), exports);
21
21
  __exportStar(require("./services/gemini-chat.service"), exports);
22
+ __exportStar(require("./services/vertex-image.service"), exports);
22
23
  __exportStar(require("./dto/generate-image.dto"), exports);
23
24
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,38 @@
1
+ export declare const DefaultBestVoice: {
2
+ en: {
3
+ woman: string;
4
+ man: string;
5
+ };
6
+ 'en-GB': {
7
+ woman: string;
8
+ man: string;
9
+ };
10
+ de: {
11
+ woman: string;
12
+ man: string;
13
+ };
14
+ 'es-ES': {
15
+ woman: string;
16
+ man: string;
17
+ };
18
+ fr: {
19
+ woman: string;
20
+ man: string;
21
+ };
22
+ es: {
23
+ woman: string;
24
+ man: string;
25
+ };
26
+ it: {
27
+ woman: string;
28
+ man: string;
29
+ };
30
+ pt: {
31
+ woman: string;
32
+ man: string;
33
+ };
34
+ ja: {
35
+ woman: string;
36
+ man: string;
37
+ };
38
+ };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultBestVoice = void 0;
4
+ exports.DefaultBestVoice = {
5
+ en: {
6
+ woman: 'en-US-Studio-O',
7
+ man: 'en-US-Studio-Q',
8
+ },
9
+ 'en-GB': {
10
+ woman: 'en-GB-Studio-B',
11
+ man: 'en-GB-Studio-C',
12
+ },
13
+ de: {
14
+ woman: 'de-DE-Studio-B',
15
+ man: 'de-DE-Studio-C',
16
+ },
17
+ 'es-ES': {
18
+ woman: 'es-ES-Studio-C',
19
+ man: 'es-ES-Studio-F',
20
+ },
21
+ fr: {
22
+ woman: 'df-FR-Studio-A',
23
+ man: 'df-FR-Studio-D',
24
+ },
25
+ es: {
26
+ woman: 'es-US-Standard-A',
27
+ man: 'es-US-Studio-B',
28
+ },
29
+ it: {
30
+ woman: 'it-IT-Standard-E',
31
+ man: 'it-IT-Neural2-F',
32
+ },
33
+ pt: {
34
+ woman: 'pt-BR-Neural2-C',
35
+ man: 'pt-BR-Chirp3-HD-Fenrir',
36
+ },
37
+ ja: {
38
+ woman: 'ja-JP-Standard-A',
39
+ man: 'ja-JP-Neural2-C',
40
+ },
41
+ };
42
+ //# sourceMappingURL=voices.js.map
@@ -14,13 +14,14 @@ const nest_tts_service_1 = require("./services/nest-tts.service");
14
14
  const nest_tts_controller_1 = require("./controllers/nest-tts.controller");
15
15
  const gemini_chat_service_1 = require("./services/gemini-chat.service");
16
16
  const gemini_chat_controller_1 = require("./controllers/gemini-chat.controller");
17
+ const vertex_image_service_1 = require("./services/vertex-image.service");
17
18
  let NestVertexModule = class NestVertexModule {
18
19
  };
19
20
  exports.NestVertexModule = NestVertexModule;
20
21
  exports.NestVertexModule = NestVertexModule = __decorate([
21
22
  (0, common_1.Module)({
22
- providers: [nest_vertex_service_1.NestVertexService, nest_tts_service_1.NestTtsService, gemini_chat_service_1.GeminiChatService],
23
- exports: [nest_vertex_service_1.NestVertexService, nest_tts_service_1.NestTtsService, gemini_chat_service_1.GeminiChatService],
23
+ providers: [nest_vertex_service_1.NestVertexService, nest_tts_service_1.NestTtsService, gemini_chat_service_1.GeminiChatService, vertex_image_service_1.ImageVertexService],
24
+ exports: [nest_vertex_service_1.NestVertexService, nest_tts_service_1.NestTtsService, gemini_chat_service_1.GeminiChatService, vertex_image_service_1.ImageVertexService],
24
25
  controllers: [nest_vertex_controller_1.NestVertexController, nest_tts_controller_1.NestTtsController, gemini_chat_controller_1.GeminiChatController],
25
26
  })
26
27
  ], NestVertexModule);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataclouder/nest-vertex",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "NestJS Vertex AI library for Dataclouder",
5
5
  "author": "dataclouder",
6
6
  "license": "MIT",
@@ -13,11 +13,13 @@ export declare class ChatMessageDict {
13
13
  export declare class GeminiChatService {
14
14
  private readonly logger;
15
15
  private readonly clientGenAi;
16
- private readonly modelName;
16
+ private readonly defaultModel;
17
17
  constructor();
18
18
  private mapToGeminiRole;
19
19
  private formatMessagesToContent;
20
- chat(messages: ChatCompletionMessageParam[]): Promise<ChatMessageDict>;
20
+ chat(messages: ChatCompletionMessageParam[], model?: string): Promise<ChatMessageDict>;
21
21
  chatStream(messages: ChatCompletionMessageParam[]): Promise<AsyncIterable<ChatMessageDict>>;
22
22
  listModels(): Promise<Record<string, string>[]>;
23
+ private extractJsonFromResponse;
24
+ chatAndExtractJson(messages: ChatCompletionMessageParam[], model?: any): Promise<any>;
23
25
  }
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.GeminiChatService = exports.ChatMessageDict = exports.ChatRole = void 0;
14
14
  const common_1 = require("@nestjs/common");
15
15
  const genai_1 = require("@google/genai");
16
+ const nest_core_1 = require("@dataclouder/nest-core");
16
17
  var ChatRole;
17
18
  (function (ChatRole) {
18
19
  ChatRole["System"] = "system";
@@ -29,14 +30,14 @@ exports.ChatMessageDict = ChatMessageDict;
29
30
  let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
30
31
  logger = new common_1.Logger(GeminiChatService_1.name);
31
32
  clientGenAi;
32
- modelName = 'gemini-1.5-flash';
33
+ defaultModel = 'gemini-2.0-flash-lite';
33
34
  constructor() {
34
35
  const apiKey = process.env.GEMINI_API_KEY;
35
36
  if (!apiKey) {
36
37
  throw new Error('GEMINI_API_KEY environment variable not set.');
37
38
  }
38
39
  this.clientGenAi = new genai_1.GoogleGenAI({ apiKey });
39
- this.logger.log(`GeminiChatService initialized with model: ${this.modelName}`);
40
+ this.logger.log(`GeminiChatService initialized with model: ${this.defaultModel}`);
40
41
  }
41
42
  mapToGeminiRole(role) {
42
43
  switch (role) {
@@ -58,11 +59,14 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
58
59
  parts: [{ text: msg.content }],
59
60
  }));
60
61
  }
61
- async chat(messages) {
62
+ async chat(messages, model = this.defaultModel) {
62
63
  if (!messages || messages.length === 0) {
63
64
  return { content: '', role: ChatRole.Assistant, metadata: { finishReason: 'NO_INPUT' } };
64
65
  }
65
- const systemMessage = messages.find((msg) => msg.role === 'system')?.content;
66
+ const systemMessage = messages
67
+ .filter((msg) => msg.role === 'system')
68
+ .map((msg) => msg.content)
69
+ .join('\n');
66
70
  if (systemMessage) {
67
71
  }
68
72
  let lastMessage = messages[messages.length - 1];
@@ -72,9 +76,9 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
72
76
  }
73
77
  const formattedContents = this.formatMessagesToContent(messages);
74
78
  try {
75
- this.logger.debug(`Sending request to Gemini model ${this.modelName} with ${formattedContents.length} content parts and system instruction: ${!!systemMessage}`);
79
+ this.logger.debug(`Sending request to Gemini model ${model} with ${formattedContents.length} content parts and system instruction: ${!!systemMessage}`);
76
80
  const response = await this.clientGenAi.models.generateContent({
77
- model: this.modelName,
81
+ model: model,
78
82
  contents: formattedContents,
79
83
  config: { systemInstruction: systemMessage },
80
84
  });
@@ -108,9 +112,9 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
108
112
  const formattedContents = this.formatMessagesToContent(messages);
109
113
  const processStream = async function* () {
110
114
  try {
111
- this.logger.debug(`Sending stream request to Gemini model ${this.modelName} with ${formattedContents.length} content parts and system instruction: ${!!systemMessage}`);
115
+ this.logger.debug(`Sending stream request to Gemini model ${this.defaultModel} with ${formattedContents.length} content parts and system instruction: ${!!systemMessage}`);
112
116
  const stream = await this.ai.models.generateContentStream({
113
- model: this.modelName,
117
+ model: this.defaultModel,
114
118
  contents: formattedContents,
115
119
  config: { systemInstruction: systemMessage },
116
120
  });
@@ -145,6 +149,50 @@ let GeminiChatService = GeminiChatService_1 = class GeminiChatService {
145
149
  { id: 'gemini-2.0-flash-live-001' },
146
150
  ];
147
151
  }
152
+ extractJsonFromResponse(content) {
153
+ const jsonMatch = content.match(/(\{[\s\S]*?\}|\[[\s\S]*?\])/);
154
+ if (!jsonMatch)
155
+ return null;
156
+ try {
157
+ return JSON.parse(jsonMatch[0]);
158
+ }
159
+ catch (error) {
160
+ this.logger.error('Error parsing JSON:', error.stack);
161
+ throw new Error(`Failed to parse JSON: ${error.message}`);
162
+ }
163
+ }
164
+ async chatAndExtractJson(messages, model) {
165
+ const response = await this.chat(messages, model);
166
+ this.logger.debug(`Initial response content: ${response.content}`);
167
+ try {
168
+ const json = this.extractJsonFromResponse(response.content);
169
+ if (json === null) {
170
+ throw new Error('No JSON found in the initial response.');
171
+ }
172
+ return json;
173
+ }
174
+ catch (initialError) {
175
+ this.logger.warn(`Initial JSON extraction failed: ${initialError.message}. Attempting recovery.`);
176
+ try {
177
+ const fixPrompt = `The previous attempt to extract JSON failed. Please analyze the following text, correct any JSON formatting errors, and return ONLY the valid JSON object or array. Do not include any explanatory text before or after the JSON itself. Text to fix: ${response.content}`;
178
+ const fixResponse = await this.chat([{ role: 'user', content: fixPrompt }], model);
179
+ this.logger.debug(`Recovery response content: ${fixResponse.content}`);
180
+ const fixedJson = this.extractJsonFromResponse(fixResponse.content);
181
+ if (fixedJson === null) {
182
+ throw new Error('No JSON found in the recovery response.');
183
+ }
184
+ this.logger.log('Successfully recovered JSON on second attempt.');
185
+ return fixedJson;
186
+ }
187
+ catch (recoveryError) {
188
+ this.logger.error(`Recovery attempt also failed: ${recoveryError.message}`, recoveryError.stack);
189
+ throw new nest_core_1.AppException({
190
+ error_message: 'Error parsing JSON after retry',
191
+ explanation: `Failed to extract valid JSON from the AI response even after a correction attempt. Initial error: ${initialError.message}. Recovery error: ${recoveryError.message}. Original response: ${response.content}`,
192
+ });
193
+ }
194
+ }
195
+ }
148
196
  };
149
197
  exports.GeminiChatService = GeminiChatService;
150
198
  exports.GeminiChatService = GeminiChatService = GeminiChatService_1 = __decorate([
@@ -9,6 +9,7 @@ export interface SynthesizeSpeechInput {
9
9
  generateTranscription?: boolean;
10
10
  speed?: string;
11
11
  speedRate?: number;
12
+ ssml?: string;
12
13
  }
13
14
  export declare class NestTtsService {
14
15
  private readonly logger;
@@ -23,12 +23,12 @@ let NestTtsService = class NestTtsService {
23
23
  return 'Hello from VertexTtsService!';
24
24
  }
25
25
  async synthesizeSpeech(input) {
26
- const { text, languageCode, ssmlGender = 'NEUTRAL', voiceName, voice, audioEncoding = 'MP3', speedRate, } = input;
26
+ const { text, languageCode, ssmlGender = 'NEUTRAL', voiceName, voice, audioEncoding = 'MP3', speedRate, ssml, } = input;
27
27
  const voiceId = voiceName || voice;
28
28
  console.log('Selected voice:', voiceId);
29
29
  const langCode = !languageCode ? voiceId.slice(0, 5) : languageCode;
30
30
  const request = {
31
- input: { text: text },
31
+ input: ssml ? { ssml } : { text },
32
32
  voice: voiceId ? { name: voiceId, languageCode: langCode } : { languageCode: langCode, ssmlGender: ssmlGender },
33
33
  audioConfig: {
34
34
  audioEncoding: audioEncoding,
@@ -8,6 +8,7 @@ export declare class NestVertexService implements OnModuleInit {
8
8
  private readonly videoModelName;
9
9
  private readonly imageModelName;
10
10
  onModuleInit(): void;
11
+ listModels(): string[];
11
12
  startVideoGeneration(generateVideoDto: GenerateVideoDto): Promise<GenerateVideosOperation>;
12
13
  checkVideoOperationStatus(operationName: string): Promise<GenerateVideosOperation>;
13
14
  startImageGeneration(generateImageDto: GenerateImageDto): Promise<GenerateImagesResponse>;
@@ -26,6 +26,9 @@ let NestVertexService = NestVertexService_1 = class NestVertexService {
26
26
  this.logger.log('GoogleGenAI client initialized successfully.');
27
27
  }
28
28
  }
29
+ listModels() {
30
+ return [''];
31
+ }
29
32
  async startVideoGeneration(generateVideoDto) {
30
33
  if (!this.genAi) {
31
34
  throw new Error('GoogleGenAI client not initialized. Check GEMINI_API_KEY.');
@@ -0,0 +1,10 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { GenerateImagesResponse } from '@google/genai';
3
+ import { GenerateImageDto } from '../dto/generate-image.dto';
4
+ export declare class ImageVertexService implements OnModuleInit {
5
+ private genAi;
6
+ private readonly logger;
7
+ private readonly imageModelName;
8
+ onModuleInit(): void;
9
+ startImageGeneration(generateImageDto: GenerateImageDto): Promise<GenerateImagesResponse>;
10
+ }
@@ -0,0 +1,60 @@
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 ImageVertexService_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ImageVertexService = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const genai_1 = require("@google/genai");
13
+ const generative_ai_1 = require("@google/generative-ai");
14
+ let ImageVertexService = ImageVertexService_1 = class ImageVertexService {
15
+ genAi;
16
+ logger = new common_1.Logger(ImageVertexService_1.name);
17
+ imageModelName = 'imagen-3.0-generate-002';
18
+ onModuleInit() {
19
+ const apiKey = process.env.GEMINI_API_KEY;
20
+ if (!apiKey) {
21
+ this.logger.error('GEMINI_API_KEY environment variable not set. NestVertexService will not function.');
22
+ }
23
+ else {
24
+ console.log('GEMINI_API_KEY environment variable set: ', apiKey);
25
+ this.genAi = new genai_1.GoogleGenAI({ apiKey });
26
+ this.logger.log('GoogleGenAI client initialized successfully.');
27
+ }
28
+ }
29
+ async startImageGeneration(generateImageDto) {
30
+ if (!this.genAi) {
31
+ throw new Error('GoogleGenAI client not initialized. Check GEMINI_API_KEY/Vertex AI setup.');
32
+ }
33
+ this.logger.log(`Starting image generation with DTO: ${JSON.stringify(generateImageDto)}`);
34
+ const imageRequest = {
35
+ model: this.imageModelName,
36
+ prompt: generateImageDto.prompt,
37
+ config: {
38
+ numberOfImages: generateImageDto.numberOfImages,
39
+ aspectRatio: generateImageDto.aspectRatio,
40
+ negativePrompt: generateImageDto.negativePrompt,
41
+ includeSafetyAttributes: false,
42
+ safetySettings: [{ threshold: generative_ai_1.HarmBlockThreshold.BLOCK_NONE }],
43
+ },
44
+ };
45
+ Object.keys(imageRequest.config).forEach((key) => imageRequest.config[key] === undefined && delete imageRequest.config[key]);
46
+ try {
47
+ const response = await this.genAi.models.generateImages(imageRequest);
48
+ return response;
49
+ }
50
+ catch (error) {
51
+ this.logger.error('Error starting image generation:', error.message || error);
52
+ throw error;
53
+ }
54
+ }
55
+ };
56
+ exports.ImageVertexService = ImageVertexService;
57
+ exports.ImageVertexService = ImageVertexService = ImageVertexService_1 = __decorate([
58
+ (0, common_1.Injectable)()
59
+ ], ImageVertexService);
60
+ //# sourceMappingURL=vertex-image.service.js.map