@mate-academy/llm-gateway 2.5.3 → 3.0.0
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/README.md +295 -110
- package/dist/LLMService.factory.d.ts +10 -19
- package/dist/LLMService.factory.js +22 -22
- package/dist/LLMService.factory.js.map +1 -1
- package/dist/LLMService.typedefs.d.ts +51 -4
- package/dist/LLMService.typedefs.js.map +1 -1
- package/dist/providers/GoogleGenerativeAI/GoogleGenerativeAI.entity.d.ts +2 -3
- package/dist/providers/GoogleGenerativeAI/GoogleGenerativeAI.entity.js +1 -1
- package/dist/providers/GoogleGenerativeAI/GoogleGenerativeAI.entity.js.map +1 -1
- package/dist/providers/GoogleGenerativeAI/GoogleGenerativeAIService.factory.d.ts +3 -4
- package/dist/providers/GoogleGenerativeAI/GoogleGenerativeAIService.factory.js +2 -1
- package/dist/providers/GoogleGenerativeAI/GoogleGenerativeAIService.factory.js.map +1 -1
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAIAssistance.service.d.ts +2 -3
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAIAssistance.service.js +8 -8
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAIAssistance.service.js.map +1 -1
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAICompletion.service.d.ts +2 -3
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAICompletion.service.js +3 -3
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAICompletion.service.js.map +1 -1
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAISpeechToText.service.d.ts +2 -3
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAISpeechToText.service.js +1 -1
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAISpeechToText.service.js.map +1 -1
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAITextToSpeech.service.d.ts +2 -3
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAITextToSpeech.service.js +1 -1
- package/dist/providers/GoogleGenerativeAI/services/GoogleGenerativeAITextToSpeech.service.js.map +1 -1
- package/dist/providers/OpenAI/OpenAI.entity.d.ts +3 -4
- package/dist/providers/OpenAI/OpenAI.entity.js +1 -1
- package/dist/providers/OpenAI/OpenAI.entity.js.map +1 -1
- package/dist/providers/OpenAI/OpenAIService.factory.d.ts +3 -4
- package/dist/providers/OpenAI/OpenAIService.factory.js +2 -1
- package/dist/providers/OpenAI/OpenAIService.factory.js.map +1 -1
- package/dist/providers/OpenAI/services/OpenAIAssistance.service.d.ts +2 -3
- package/dist/providers/OpenAI/services/OpenAIAssistance.service.js +7 -7
- package/dist/providers/OpenAI/services/OpenAIAssistance.service.js.map +1 -1
- package/dist/providers/OpenAI/services/OpenAICompletion.service.d.ts +2 -3
- package/dist/providers/OpenAI/services/OpenAICompletion.service.js +3 -3
- package/dist/providers/OpenAI/services/OpenAICompletion.service.js.map +1 -1
- package/dist/providers/OpenAI/services/OpenAISpeechToText.service.d.ts +2 -3
- package/dist/providers/OpenAI/services/OpenAISpeechToText.service.js +1 -1
- package/dist/providers/OpenAI/services/OpenAISpeechToText.service.js.map +1 -1
- package/dist/providers/OpenAI/services/OpenAITextToSpeech.service.d.ts +2 -3
- package/dist/providers/OpenAI/services/OpenAITextToSpeech.service.js +1 -1
- package/dist/providers/OpenAI/services/OpenAITextToSpeech.service.js.map +1 -1
- package/dist/services/LLMAssistanceService.abstract.d.ts +2 -3
- package/dist/services/LLMAssistanceService.abstract.js.map +1 -1
- package/dist/services/LLMBaseService.abstract.d.ts +3 -4
- package/dist/services/LLMBaseService.abstract.js +1 -1
- package/dist/services/LLMBaseService.abstract.js.map +1 -1
- package/dist/services/LLMCompletionService.abstract.d.ts +2 -3
- package/dist/services/LLMCompletionService.abstract.js.map +1 -1
- package/dist/services/LLMServicePurposeFactory.abstract.d.ts +7 -3
- package/dist/services/LLMServicePurposeFactory.abstract.js.map +1 -1
- package/dist/services/LLMSpeechToTextService.abstract.d.ts +2 -3
- package/dist/services/LLMSpeechToTextService.abstract.js.map +1 -1
- package/dist/services/LLMTextToSpeechService.abstract.d.ts +2 -3
- package/dist/services/LLMTextToSpeechService.abstract.js.map +1 -1
- package/package.json +8 -9
package/README.md
CHANGED
|
@@ -30,6 +30,23 @@ npm install @mate-academy/llm-gateway
|
|
|
30
30
|
|
|
31
31
|
## Usage
|
|
32
32
|
|
|
33
|
+
### Logger Interface
|
|
34
|
+
|
|
35
|
+
The package accepts an optional logger that implements the `LLMLogger` interface. Most logging libraries are compatible (`@mate-academy/logger`, winston, pino, etc.). If no logger is provided, no logging will occur.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Using @mate-academy/logger (recommended)
|
|
39
|
+
import { logger } from '@mate-academy/logger';
|
|
40
|
+
|
|
41
|
+
// Or simple console logger
|
|
42
|
+
const logger = {
|
|
43
|
+
info: (msg, meta) => console.log(msg, meta),
|
|
44
|
+
error: (msg, meta) => console.error(msg, meta),
|
|
45
|
+
warn: (msg, meta) => console.warn(msg, meta),
|
|
46
|
+
child: (context) => logger,
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
33
50
|
### Basic Setup
|
|
34
51
|
|
|
35
52
|
```typescript
|
|
@@ -47,6 +64,7 @@ import {
|
|
|
47
64
|
LLMModel,
|
|
48
65
|
LLMSchema,
|
|
49
66
|
createPromptTemplate,
|
|
67
|
+
LLMLogger,
|
|
50
68
|
} from '@mate-academy/llm-gateway';
|
|
51
69
|
|
|
52
70
|
// Define provider options
|
|
@@ -65,32 +83,32 @@ const llmProviderOptions = LLMServiceFactory.resolveProviderOptions(
|
|
|
65
83
|
);
|
|
66
84
|
|
|
67
85
|
// Get completion service
|
|
68
|
-
const completionService = LLMServiceFactory.getCompletionService(
|
|
69
|
-
LLMProviders.OpenAI,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
);
|
|
86
|
+
const completionService = LLMServiceFactory.getCompletionService({
|
|
87
|
+
provider: LLMProviders.OpenAI,
|
|
88
|
+
options: llmProviderOptions,
|
|
89
|
+
logger, // optional - omit for no logging
|
|
90
|
+
});
|
|
73
91
|
|
|
74
92
|
// Get assistance service
|
|
75
|
-
const assistanceService = LLMServiceFactory.getAssistanceService(
|
|
76
|
-
LLMProviders.OpenAI,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
);
|
|
93
|
+
const assistanceService = LLMServiceFactory.getAssistanceService({
|
|
94
|
+
provider: LLMProviders.OpenAI,
|
|
95
|
+
options: llmProviderOptions,
|
|
96
|
+
logger, // optional - omit for no logging
|
|
97
|
+
});
|
|
80
98
|
|
|
81
99
|
// Get speech-to-text service
|
|
82
|
-
const speechToTextService = LLMServiceFactory.getSpeechToTextService(
|
|
83
|
-
LLMProviders.OpenAI,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
100
|
+
const speechToTextService = LLMServiceFactory.getSpeechToTextService({
|
|
101
|
+
provider: LLMProviders.OpenAI,
|
|
102
|
+
options: llmProviderOptions,
|
|
103
|
+
logger, // optional - omit for no logging
|
|
104
|
+
});
|
|
87
105
|
|
|
88
106
|
// Get text-to-speech service
|
|
89
|
-
const textToSpeechService = LLMServiceFactory.getTextToSpeechService(
|
|
90
|
-
LLMProviders.OpenAI,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
);
|
|
107
|
+
const textToSpeechService = LLMServiceFactory.getTextToSpeechService({
|
|
108
|
+
provider: LLMProviders.OpenAI,
|
|
109
|
+
options: llmProviderOptions,
|
|
110
|
+
logger, // optional - omit for no logging
|
|
111
|
+
});
|
|
94
112
|
```
|
|
95
113
|
|
|
96
114
|
### Real-world Example
|
|
@@ -128,29 +146,29 @@ class MyUseCase {
|
|
|
128
146
|
},
|
|
129
147
|
);
|
|
130
148
|
|
|
131
|
-
this.llmCompletionService = LLMServiceFactory.getCompletionService(
|
|
132
|
-
config.llmProvider,
|
|
149
|
+
this.llmCompletionService = LLMServiceFactory.getCompletionService({
|
|
150
|
+
provider: config.llmProvider,
|
|
151
|
+
options: llmProviderOptions,
|
|
133
152
|
logger,
|
|
134
|
-
|
|
135
|
-
);
|
|
153
|
+
});
|
|
136
154
|
|
|
137
|
-
this.llmAssistanceService = LLMServiceFactory.getAssistanceService(
|
|
138
|
-
config.llmProvider,
|
|
155
|
+
this.llmAssistanceService = LLMServiceFactory.getAssistanceService({
|
|
156
|
+
provider: config.llmProvider,
|
|
157
|
+
options: llmProviderOptions,
|
|
139
158
|
logger,
|
|
140
|
-
|
|
141
|
-
);
|
|
159
|
+
});
|
|
142
160
|
|
|
143
|
-
this.llmSpeechToTextService = LLMServiceFactory.getSpeechToTextService(
|
|
144
|
-
config.llmProvider,
|
|
161
|
+
this.llmSpeechToTextService = LLMServiceFactory.getSpeechToTextService({
|
|
162
|
+
provider: config.llmProvider,
|
|
163
|
+
options: llmProviderOptions,
|
|
145
164
|
logger,
|
|
146
|
-
|
|
147
|
-
);
|
|
165
|
+
});
|
|
148
166
|
|
|
149
|
-
this.llmTextToSpeechService = LLMServiceFactory.getTextToSpeechService(
|
|
150
|
-
config.llmProvider,
|
|
167
|
+
this.llmTextToSpeechService = LLMServiceFactory.getTextToSpeechService({
|
|
168
|
+
provider: config.llmProvider,
|
|
169
|
+
options: llmProviderOptions,
|
|
151
170
|
logger,
|
|
152
|
-
|
|
153
|
-
);
|
|
171
|
+
});
|
|
154
172
|
}
|
|
155
173
|
|
|
156
174
|
async processRequest(prompt) {
|
|
@@ -257,7 +275,7 @@ const result = await completionService.sendMessage({
|
|
|
257
275
|
// Type-safe access to structured data
|
|
258
276
|
if (result.data) {
|
|
259
277
|
console.log(result.data.name); // string
|
|
260
|
-
console.log(result.data.age); // number
|
|
278
|
+
console.log(result.data.age); // number
|
|
261
279
|
console.log(result.data.email); // string
|
|
262
280
|
console.log(result.data.isActive); // boolean
|
|
263
281
|
}
|
|
@@ -380,6 +398,59 @@ if (result.data) {
|
|
|
380
398
|
- Use `.min()` and `.max()` instead of `.positive()`, `.negative()`
|
|
381
399
|
- Test schemas with both providers if cross-compatibility is important
|
|
382
400
|
|
|
401
|
+
### Model Configuration
|
|
402
|
+
|
|
403
|
+
Each model comes with default configuration values that can be customized for your specific needs.
|
|
404
|
+
|
|
405
|
+
#### Accessing and Customizing Models
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
// Get available models from the service
|
|
409
|
+
const models = completionService.models;
|
|
410
|
+
|
|
411
|
+
// Get a specific model
|
|
412
|
+
const model = models[OpenAIModelNames.GPT_4_OMNI];
|
|
413
|
+
|
|
414
|
+
// Customize model configuration
|
|
415
|
+
const customModel = {
|
|
416
|
+
...model,
|
|
417
|
+
config: {
|
|
418
|
+
...model.config,
|
|
419
|
+
temperature: 0.8, // Override temperature (0-2, controls randomness)
|
|
420
|
+
top_p: 0.9, // Override top_p (nucleus sampling)
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
// Use customized model in requests
|
|
425
|
+
const result = await completionService.sendMessage({
|
|
426
|
+
message: {
|
|
427
|
+
role: LLMRoles.User,
|
|
428
|
+
content: [{ type: LLMMessageContentType.TEXT, text: 'Hello!' }]
|
|
429
|
+
},
|
|
430
|
+
model: customModel,
|
|
431
|
+
});
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
#### Model-Specific Configuration
|
|
435
|
+
|
|
436
|
+
**GPT-5 Models** have special configuration options:
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
const gpt5Model = models[OpenAIModelNames.GPT_5];
|
|
440
|
+
|
|
441
|
+
const customGPT5Model = {
|
|
442
|
+
...gpt5Model,
|
|
443
|
+
config: {
|
|
444
|
+
...gpt5Model.config,
|
|
445
|
+
temperature: 1, // Note: GPT-5 only supports temperature=1
|
|
446
|
+
reasoning_effort: 'high', // 'minimal' | 'medium' | 'high'
|
|
447
|
+
verbosity: 'low', // 'low' | 'medium' | 'high'
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Note:** GPT-5 models require `temperature: 1` and cannot be changed. GPT-5-MINI only supports the default temperature.
|
|
453
|
+
|
|
383
454
|
#### File-based Assistance
|
|
384
455
|
|
|
385
456
|
```typescript
|
|
@@ -390,11 +461,11 @@ const uploadedFile = await assistanceService.uploadFile({
|
|
|
390
461
|
mimeType: LLMUploadFileMimeTypes.PLAIN_TEXT,
|
|
391
462
|
});
|
|
392
463
|
|
|
393
|
-
// Create file storage
|
|
464
|
+
// Create file storage with instructions
|
|
394
465
|
const storage = await assistanceService.createFileStorage({
|
|
395
466
|
uploadedFiles: [uploadedFile],
|
|
396
467
|
model: preferredModel,
|
|
397
|
-
instructions: 'Help me analyze this document',
|
|
468
|
+
instructions: 'Help me analyze this document', // Optional context for the storage
|
|
398
469
|
});
|
|
399
470
|
|
|
400
471
|
// Create chat with file context
|
|
@@ -403,7 +474,7 @@ const chat = await assistanceService.createChat({
|
|
|
403
474
|
model: preferredModel,
|
|
404
475
|
history: [],
|
|
405
476
|
files: [uploadedFile],
|
|
406
|
-
instructions: 'Answer questions about the uploaded document',
|
|
477
|
+
instructions: 'Answer questions about the uploaded document', // Initial assistant instructions
|
|
407
478
|
});
|
|
408
479
|
```
|
|
409
480
|
|
|
@@ -414,7 +485,7 @@ const transcription = await speechToTextService.transcribe({
|
|
|
414
485
|
pathToAudio: '/path/to/audio.mp3',
|
|
415
486
|
mimeType: LLMUploadFileMimeTypes.AUDIO_MP3, // Optional, but recommended
|
|
416
487
|
model: preferredModel,
|
|
417
|
-
instructions: 'Transcribe the audio file', // Optional
|
|
488
|
+
instructions: 'Transcribe the audio file', // Optional: custom prompt for transcription context
|
|
418
489
|
});
|
|
419
490
|
|
|
420
491
|
console.log(transcription.text); // Transcribed text
|
|
@@ -563,6 +634,12 @@ Interface for text completion services.
|
|
|
563
634
|
#### Methods
|
|
564
635
|
|
|
565
636
|
- `sendMessage(options)`: Send a message to the LLM and get a completion response
|
|
637
|
+
- `message`: The message to send
|
|
638
|
+
- `model`: The LLM model to use (with optional config overrides)
|
|
639
|
+
- `history`: Optional conversation history
|
|
640
|
+
- `instructions`: Optional system instructions to guide the model's behavior
|
|
641
|
+
- `schema`: Optional schema for structured output
|
|
642
|
+
- `abortSignal`: Optional abort signal for cancellation
|
|
566
643
|
|
|
567
644
|
### LLMAssistanceService
|
|
568
645
|
|
|
@@ -573,10 +650,22 @@ Interface for chat/assistance services with file handling capabilities.
|
|
|
573
650
|
- `uploadFile(fileOptions)`: Upload a file to the LLM service
|
|
574
651
|
- `deleteFile(fileId)`: Delete a file from the LLM service
|
|
575
652
|
- `createFileStorage(options)`: Create a file storage for organizing files
|
|
653
|
+
- `uploadedFiles`: Array of previously uploaded files
|
|
654
|
+
- `model`: The LLM model to use
|
|
655
|
+
- `instructions`: Optional instructions for how to use the stored files
|
|
576
656
|
- `deleteFileStorage(fileStorageId)`: Delete a file storage
|
|
577
657
|
- `createAssistant(options)`: Create an AI assistant with specific instructions
|
|
658
|
+
- `model`: The LLM model to use
|
|
659
|
+
- `instructions`: Optional instructions defining the assistant's behavior
|
|
660
|
+
- `storageIds`: Optional array of storage IDs to give the assistant access to
|
|
661
|
+
- `name`: Optional name for the assistant
|
|
578
662
|
- `deleteAssistant(assistantId)`: Delete an assistant
|
|
579
663
|
- `createChat(options)`: Create a new chat/conversation
|
|
664
|
+
- `model`: The LLM model to use
|
|
665
|
+
- `instructions`: Optional initial instructions for the conversation
|
|
666
|
+
- `history`: Optional conversation history
|
|
667
|
+
- `files`: Optional array of uploaded files
|
|
668
|
+
- `storageId`: Optional storage ID to use
|
|
580
669
|
- `deleteChat(chatId)`: Delete a chat
|
|
581
670
|
- `assistInChat(options)`: Send a message in an existing chat and get an assistant response
|
|
582
671
|
- `countTokens(messages, model)`: Count tokens in messages for context management
|
|
@@ -588,6 +677,10 @@ Interface for converting speech audio to text.
|
|
|
588
677
|
#### Methods
|
|
589
678
|
|
|
590
679
|
- `transcribe(options)`: Convert audio file to text transcription
|
|
680
|
+
- `pathToAudio`: Path to the audio file
|
|
681
|
+
- `mimeType`: Optional MIME type of the audio file
|
|
682
|
+
- `model`: The LLM model to use
|
|
683
|
+
- `instructions`: Optional custom transcription prompt or context
|
|
591
684
|
|
|
592
685
|
### LLMTextToSpeechService
|
|
593
686
|
|
|
@@ -665,6 +758,7 @@ const fullLesson = coursePrompt({
|
|
|
665
758
|
const basicLesson = coursePrompt({
|
|
666
759
|
topicTitle: 'React Hooks',
|
|
667
760
|
hasPrerequisites: false,
|
|
761
|
+
prerequisites: '',
|
|
668
762
|
includeExercises: false,
|
|
669
763
|
difficultyLevel: 'beginner'
|
|
670
764
|
});
|
|
@@ -733,7 +827,7 @@ const reviewInstruction = codeReviewPrompt({
|
|
|
733
827
|
outputFormat: 'structured',
|
|
734
828
|
includeCode: true,
|
|
735
829
|
codeSnippet: 'function example() { /* code here */ }',
|
|
736
|
-
provideExamples: false
|
|
830
|
+
provideExamples: false,
|
|
737
831
|
});
|
|
738
832
|
```
|
|
739
833
|
|
|
@@ -887,15 +981,33 @@ Creates a prompt template function from a template string.
|
|
|
887
981
|
Supports all service types: completion, assistance, speech-to-text, and text-to-speech APIs. For more information, see [OpenAI API documentation](https://platform.openai.com/docs/api-reference).
|
|
888
982
|
|
|
889
983
|
**Available Models:**
|
|
890
|
-
|
|
891
|
-
|
|
984
|
+
|
|
985
|
+
| Model | Purpose | Max Input | Max Output | Notes |
|
|
986
|
+
|-------|---------|-----------|------------|-------|
|
|
987
|
+
| gpt-4o | Completion, Assistance | 128K | 16K | General purpose, balanced |
|
|
988
|
+
| gpt-4o-mini | Completion, Assistance | 128K | 16K | Faster, cost-effective |
|
|
989
|
+
| gpt-4.1 | Completion, Assistance | 1M+ | 32K | Extended context window |
|
|
990
|
+
| gpt-5 | Completion, Assistance | 400K | 128K | Advanced reasoning, requires temperature=1 |
|
|
991
|
+
| gpt-5-mini | Completion, Assistance | 400K | 128K | Smaller GPT-5 variant |
|
|
992
|
+
| gpt-4o-transcribe | Speech-to-Text | 16K | 2K | Optimized for transcription |
|
|
993
|
+
| gpt-4o-mini-transcribe | Speech-to-Text | 16K | 2K | Cost-effective transcription |
|
|
994
|
+
| tts-1 | Text-to-Speech | - | - | Standard TTS model |
|
|
995
|
+
| gpt-4o-mini-tts | Text-to-Speech | - | - | Alternative TTS model |
|
|
892
996
|
|
|
893
997
|
### Google Generative AI
|
|
894
998
|
|
|
895
|
-
Supports completion and
|
|
999
|
+
Supports completion, assistance, speech-to-text, and text-to-speech APIs through Google's Generative AI models. For more information, see [Google Generative AI documentation](https://ai.google.dev/docs).
|
|
896
1000
|
|
|
897
1001
|
**Available Models:**
|
|
898
|
-
|
|
1002
|
+
|
|
1003
|
+
| Model | Purpose | Max Input | Max Output | Notes |
|
|
1004
|
+
|-------|---------|-----------|------------|-------|
|
|
1005
|
+
| gemini-2.5-flash | Completion, Assistance, Speech-to-Text | 1M+ | 65K | Fast, cost-effective, supports caching for long context |
|
|
1006
|
+
| gemini-2.5-pro | Completion, Assistance, Speech-to-Text | 1M+ | 65K | Advanced reasoning, supports caching for long context |
|
|
1007
|
+
| gemini-2.5-flash-preview-tts | Text-to-Speech | 8K | 16K | Preview TTS model with flash performance |
|
|
1008
|
+
| gemini-2.5-pro-preview-tts | Text-to-Speech | 8K | 16K | Preview TTS model with pro capabilities |
|
|
1009
|
+
|
|
1010
|
+
**Note:** Google Generative AI models support context caching for content longer than 32,768 tokens, which can significantly reduce costs for repeated queries on the same large context.
|
|
899
1011
|
|
|
900
1012
|
## Testing
|
|
901
1013
|
|
|
@@ -968,33 +1080,84 @@ The integration tests cover:
|
|
|
968
1080
|
|
|
969
1081
|
The package provides several test utilities:
|
|
970
1082
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
resolveTestConfig,
|
|
975
|
-
hasText,
|
|
976
|
-
hasError,
|
|
977
|
-
} from '@mate-academy/llm-gateway/tests/helpers';
|
|
1083
|
+
#### resolveTestConfig Function
|
|
1084
|
+
|
|
1085
|
+
The `resolveTestConfig` function creates standardized test configurations for all supported providers based on the service purpose:
|
|
978
1086
|
|
|
979
|
-
|
|
980
|
-
|
|
1087
|
+
```typescript
|
|
1088
|
+
import { resolveTestConfig } from '@mate-academy/llm-gateway/tests/helpers';
|
|
981
1089
|
|
|
982
|
-
// Get test
|
|
1090
|
+
// Get test config for completion services
|
|
983
1091
|
const testConfig = resolveTestConfig(LLMPurposes.Completion);
|
|
984
1092
|
|
|
1093
|
+
// testConfig contains configuration for all providers:
|
|
1094
|
+
// {
|
|
1095
|
+
// [LLMProviders.OpenAI]: {
|
|
1096
|
+
// provider: LLMProviders.OpenAI,
|
|
1097
|
+
// availableModels: {...}, // Models available for completion
|
|
1098
|
+
// clientOptions: { apiKey: process.env.OPENAI_SECRET_API_KEY, ... },
|
|
1099
|
+
// requireCredentials: () => void, // Throws if credentials missing
|
|
1100
|
+
// isEnabled: true
|
|
1101
|
+
// },
|
|
1102
|
+
// [LLMProviders.GoogleGenerativeAI]: {
|
|
1103
|
+
// provider: LLMProviders.GoogleGenerativeAI,
|
|
1104
|
+
// availableModels: {...}, // Models available for completion
|
|
1105
|
+
// clientOptions: { apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY },
|
|
1106
|
+
// requireCredentials: () => void, // Throws if credentials missing
|
|
1107
|
+
// isEnabled: true
|
|
1108
|
+
// }
|
|
1109
|
+
// }
|
|
1110
|
+
|
|
1111
|
+
// Use in tests to iterate over all providers
|
|
1112
|
+
Object.values(testConfig).forEach((config) => {
|
|
1113
|
+
const { provider, clientOptions, availableModels, requireCredentials } = config;
|
|
1114
|
+
|
|
1115
|
+
describe(`${provider} Provider`, () => {
|
|
1116
|
+
beforeAll(() => {
|
|
1117
|
+
requireCredentials(); // Ensures API keys are present
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
it('should create service', () => {
|
|
1121
|
+
const service = LLMServiceFactory.getCompletionService({
|
|
1122
|
+
provider,
|
|
1123
|
+
options: clientOptions,
|
|
1124
|
+
logger: mockLogger, // Optional
|
|
1125
|
+
});
|
|
1126
|
+
expect(service).toBeDefined();
|
|
1127
|
+
});
|
|
1128
|
+
});
|
|
1129
|
+
});
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
#### Mock Logger
|
|
1133
|
+
|
|
1134
|
+
```typescript
|
|
1135
|
+
// Note: Test helpers are for internal use only
|
|
1136
|
+
// When testing your integration, create your own mock logger:
|
|
1137
|
+
const mockLogger = {
|
|
1138
|
+
info: jest.fn(),
|
|
1139
|
+
error: jest.fn(),
|
|
1140
|
+
warn: jest.fn(),
|
|
1141
|
+
child: jest.fn(() => mockLogger),
|
|
1142
|
+
};
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
#### Type Guards
|
|
1146
|
+
|
|
1147
|
+
```typescript
|
|
985
1148
|
// Type guards for test assertions
|
|
986
|
-
if (
|
|
1149
|
+
if ('text' in result && result.text) {
|
|
987
1150
|
expect(result.text).toContain('expected content');
|
|
988
1151
|
}
|
|
989
1152
|
|
|
990
|
-
if (
|
|
1153
|
+
if ('error' in result && result.error) {
|
|
991
1154
|
expect(result.error).toBeDefined();
|
|
992
1155
|
}
|
|
993
1156
|
```
|
|
994
1157
|
|
|
995
1158
|
### Writing Custom Tests
|
|
996
1159
|
|
|
997
|
-
Example of writing a custom integration test
|
|
1160
|
+
Example of writing a custom integration test using `resolveTestConfig`:
|
|
998
1161
|
|
|
999
1162
|
```typescript
|
|
1000
1163
|
import {
|
|
@@ -1007,27 +1170,55 @@ import {
|
|
|
1007
1170
|
LLMServiceFactory,
|
|
1008
1171
|
LLMProviders,
|
|
1009
1172
|
LLMPurposes,
|
|
1173
|
+
resolveTestConfig,
|
|
1010
1174
|
} from '@mate-academy/llm-gateway';
|
|
1011
|
-
|
|
1175
|
+
|
|
1176
|
+
// Create your own mock logger
|
|
1177
|
+
const mockLogger = {
|
|
1178
|
+
info: jest.fn(),
|
|
1179
|
+
error: jest.fn(),
|
|
1180
|
+
warn: jest.fn(),
|
|
1181
|
+
child: jest.fn(() => mockLogger),
|
|
1182
|
+
};
|
|
1012
1183
|
|
|
1013
1184
|
describe('Custom LLM Integration Test', () => {
|
|
1185
|
+
// Use resolveTestConfig for consistent test configuration
|
|
1014
1186
|
const testConfig = resolveTestConfig(LLMPurposes.Completion);
|
|
1015
1187
|
|
|
1016
|
-
|
|
1188
|
+
// Test all enabled providers
|
|
1189
|
+
Object.values(testConfig).forEach((config) => {
|
|
1190
|
+
const { provider, clientOptions, requireCredentials } = config;
|
|
1191
|
+
|
|
1017
1192
|
describe(`${provider} Provider`, () => {
|
|
1018
1193
|
let service;
|
|
1019
1194
|
|
|
1020
1195
|
beforeAll(() => {
|
|
1021
|
-
requireCredentials();
|
|
1022
|
-
|
|
1196
|
+
requireCredentials(); // Validates API keys are present
|
|
1197
|
+
|
|
1198
|
+
service = LLMServiceFactory.getCompletionService({
|
|
1023
1199
|
provider,
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
);
|
|
1200
|
+
options: clientOptions,
|
|
1201
|
+
logger: mockLogger, // Optional - can be omitted
|
|
1202
|
+
});
|
|
1027
1203
|
});
|
|
1028
1204
|
|
|
1029
1205
|
it('should process custom request', async () => {
|
|
1030
1206
|
// Your custom test logic here
|
|
1207
|
+
const result = await service.sendMessage({
|
|
1208
|
+
message: {
|
|
1209
|
+
role: LLMRoles.User,
|
|
1210
|
+
content: [{ type: LLMMessageContentType.TEXT, text: 'Test message' }],
|
|
1211
|
+
},
|
|
1212
|
+
model: Object.values(config.availableModels)[0], // Use first available model
|
|
1213
|
+
});
|
|
1214
|
+
|
|
1215
|
+
// Use type guards for assertions
|
|
1216
|
+
if ('text' in result && result.text) {
|
|
1217
|
+
expect(result.text).toBeDefined();
|
|
1218
|
+
expect(typeof result.text).toBe('string');
|
|
1219
|
+
} else if ('error' in result && result.error) {
|
|
1220
|
+
throw result.error;
|
|
1221
|
+
}
|
|
1031
1222
|
});
|
|
1032
1223
|
});
|
|
1033
1224
|
});
|
|
@@ -1238,21 +1429,21 @@ Create service implementations in the `services` directory:
|
|
|
1238
1429
|
**CompletionService (src/providers/YourProvider/services/YourProviderCompletionService.ts)**:
|
|
1239
1430
|
|
|
1240
1431
|
```typescript
|
|
1241
|
-
import {
|
|
1432
|
+
import { LLMLogger } from '../../../LLMService.typedefs';
|
|
1242
1433
|
import { LLMCompletionService } from '../../../services/LLMCompletionService.abstract';
|
|
1243
1434
|
import { CompletionParams, CompletionResult, LLMProviders } from '../../../LLMService.typedefs';
|
|
1244
1435
|
import { YourProviderEntity } from '../YourProvider.entity';
|
|
1245
1436
|
|
|
1246
1437
|
export class YourProviderCompletionService extends LLMCompletionService<LLMProviders.YourProvider> {
|
|
1247
1438
|
constructor(
|
|
1248
|
-
logger:
|
|
1439
|
+
logger: LLMLogger | undefined,
|
|
1249
1440
|
private readonly providerEntity: YourProviderEntity,
|
|
1250
1441
|
) {
|
|
1251
1442
|
super(logger);
|
|
1252
1443
|
}
|
|
1253
1444
|
|
|
1254
1445
|
async complete(params: CompletionParams): Promise<CompletionResult> {
|
|
1255
|
-
this.logger
|
|
1446
|
+
this.logger?.info('Starting completion with YourProvider', { params });
|
|
1256
1447
|
|
|
1257
1448
|
try {
|
|
1258
1449
|
// Implement provider-specific completion logic
|
|
@@ -1262,7 +1453,7 @@ export class YourProviderCompletionService extends LLMCompletionService<LLMProvi
|
|
|
1262
1453
|
// Include other required fields
|
|
1263
1454
|
};
|
|
1264
1455
|
} catch (error) {
|
|
1265
|
-
this.logger
|
|
1456
|
+
this.logger?.error('Error in YourProvider completion', { error });
|
|
1266
1457
|
throw error;
|
|
1267
1458
|
}
|
|
1268
1459
|
}
|
|
@@ -1272,7 +1463,7 @@ export class YourProviderCompletionService extends LLMCompletionService<LLMProvi
|
|
|
1272
1463
|
**AssistanceService (if applicable)**:
|
|
1273
1464
|
|
|
1274
1465
|
```typescript
|
|
1275
|
-
import {
|
|
1466
|
+
import { LLMLogger } from '../../../LLMService.typedefs';
|
|
1276
1467
|
import { LLMAssistanceService } from '../../../services/LLMAssistanceService.abstract';
|
|
1277
1468
|
import {
|
|
1278
1469
|
LLMAssistanceOptions,
|
|
@@ -1283,7 +1474,7 @@ import { YourProviderEntity } from '../YourProvider.entity';
|
|
|
1283
1474
|
|
|
1284
1475
|
export class YourProviderAssistanceService extends LLMAssistanceService<LLMProviders.YourProvider> {
|
|
1285
1476
|
constructor(
|
|
1286
|
-
logger:
|
|
1477
|
+
logger: LLMLogger,
|
|
1287
1478
|
private readonly providerEntity: YourProviderEntity,
|
|
1288
1479
|
) {
|
|
1289
1480
|
super(logger);
|
|
@@ -1311,7 +1502,7 @@ export class YourProviderAssistanceService extends LLMAssistanceService<LLMProvi
|
|
|
1311
1502
|
**SpeechToTextService (if applicable)**:
|
|
1312
1503
|
|
|
1313
1504
|
```typescript
|
|
1314
|
-
import {
|
|
1505
|
+
import { LLMLogger } from '../../../LLMService.typedefs';
|
|
1315
1506
|
import { LLMSpeechToTextService } from '../../../services/LLMSpeechToTextService.abstract';
|
|
1316
1507
|
import {
|
|
1317
1508
|
LLMTranscribeOptions,
|
|
@@ -1322,14 +1513,14 @@ import { YourProviderEntity } from '../YourProvider.entity';
|
|
|
1322
1513
|
|
|
1323
1514
|
export class YourProviderSpeechToTextService extends LLMSpeechToTextService<LLMProviders.YourProvider> {
|
|
1324
1515
|
constructor(
|
|
1325
|
-
logger:
|
|
1516
|
+
logger: LLMLogger | undefined,
|
|
1326
1517
|
private readonly providerEntity: YourProviderEntity,
|
|
1327
1518
|
) {
|
|
1328
1519
|
super(logger);
|
|
1329
1520
|
}
|
|
1330
1521
|
|
|
1331
1522
|
async transcribe(options: LLMTranscribeOptions<typeof this.provider>): Promise<LLMTranscribeResult> {
|
|
1332
|
-
this.logger
|
|
1523
|
+
this.logger?.info('Starting transcription with YourProvider', { options });
|
|
1333
1524
|
|
|
1334
1525
|
try {
|
|
1335
1526
|
// Implement provider-specific transcription logic
|
|
@@ -1337,7 +1528,7 @@ export class YourProviderSpeechToTextService extends LLMSpeechToTextService<LLMP
|
|
|
1337
1528
|
text: 'Transcribed text from audio',
|
|
1338
1529
|
};
|
|
1339
1530
|
} catch (error) {
|
|
1340
|
-
this.logger
|
|
1531
|
+
this.logger?.error('Error in YourProvider transcription', { error });
|
|
1341
1532
|
throw error;
|
|
1342
1533
|
}
|
|
1343
1534
|
}
|
|
@@ -1347,7 +1538,7 @@ export class YourProviderSpeechToTextService extends LLMSpeechToTextService<LLMP
|
|
|
1347
1538
|
**TextToSpeechService (if applicable)**:
|
|
1348
1539
|
|
|
1349
1540
|
```typescript
|
|
1350
|
-
import {
|
|
1541
|
+
import { LLMLogger } from '../../../LLMService.typedefs';
|
|
1351
1542
|
import { LLMTextToSpeechService } from '../../../services/LLMTextToSpeechService.abstract';
|
|
1352
1543
|
import {
|
|
1353
1544
|
LLMCreateSpeechOptions,
|
|
@@ -1358,14 +1549,14 @@ import { YourProviderEntity } from '../YourProvider.entity';
|
|
|
1358
1549
|
|
|
1359
1550
|
export class YourProviderTextToSpeechService extends LLMTextToSpeechService<LLMProviders.YourProvider> {
|
|
1360
1551
|
constructor(
|
|
1361
|
-
logger:
|
|
1552
|
+
logger: LLMLogger | undefined,
|
|
1362
1553
|
private readonly providerEntity: YourProviderEntity,
|
|
1363
1554
|
) {
|
|
1364
1555
|
super(logger);
|
|
1365
1556
|
}
|
|
1366
1557
|
|
|
1367
1558
|
async createSpeech(options: LLMCreateSpeechOptions<typeof this.provider>): Promise<LLMCreateSpeechResult> {
|
|
1368
|
-
this.logger
|
|
1559
|
+
this.logger?.info('Starting speech creation with YourProvider', { options });
|
|
1369
1560
|
|
|
1370
1561
|
try {
|
|
1371
1562
|
// Implement provider-specific speech creation logic
|
|
@@ -1374,7 +1565,7 @@ export class YourProviderTextToSpeechService extends LLMTextToSpeechService<LLMP
|
|
|
1374
1565
|
mimeType: 'audio/mp3',
|
|
1375
1566
|
};
|
|
1376
1567
|
} catch (error) {
|
|
1377
|
-
this.logger
|
|
1568
|
+
this.logger?.error('Error in YourProvider speech creation', { error });
|
|
1378
1569
|
throw error;
|
|
1379
1570
|
}
|
|
1380
1571
|
}
|
|
@@ -1412,14 +1603,13 @@ export const YOUR_PROVIDER_SERVICE_BUILDERS: {
|
|
|
1412
1603
|
Then, implement the service factory in `src/providers/YourProvider/YourProviderService.factory.ts`:
|
|
1413
1604
|
|
|
1414
1605
|
```typescript
|
|
1415
|
-
import { type Logger } from '@mate-academy/core';
|
|
1416
1606
|
import {
|
|
1417
1607
|
type LLMInstanceOptions,
|
|
1418
1608
|
LLMProviders,
|
|
1419
1609
|
type LLMPurposes,
|
|
1420
1610
|
type LLMServiceByPurpose,
|
|
1421
1611
|
} from '../../LLMService.typedefs';
|
|
1422
|
-
import { LLMServicePurposeFactory } from '../../services';
|
|
1612
|
+
import { LLMServicePurposeFactory, type LLMCreateServiceOptions } from '../../services';
|
|
1423
1613
|
import { YOUR_PROVIDER_SERVICE_BUILDERS } from './YourProvider.constants';
|
|
1424
1614
|
|
|
1425
1615
|
export class YourProviderServiceFactory extends LLMServicePurposeFactory<
|
|
@@ -1428,10 +1618,9 @@ export class YourProviderServiceFactory extends LLMServicePurposeFactory<
|
|
|
1428
1618
|
createService<
|
|
1429
1619
|
Purpose extends LLMPurposes
|
|
1430
1620
|
>(
|
|
1431
|
-
|
|
1432
|
-
logger: Logger,
|
|
1433
|
-
options: LLMInstanceOptions[LLMProviders.YourProvider],
|
|
1621
|
+
serviceOptions: LLMCreateServiceOptions<LLMProviders.YourProvider, Purpose>,
|
|
1434
1622
|
): LLMServiceByPurpose<LLMProviders.YourProvider>[Purpose] {
|
|
1623
|
+
const { purpose, logger, options } = serviceOptions;
|
|
1435
1624
|
const serviceBuilder = YOUR_PROVIDER_SERVICE_BUILDERS[purpose];
|
|
1436
1625
|
|
|
1437
1626
|
if (!serviceBuilder) {
|
|
@@ -1469,7 +1658,7 @@ Modify `src/LLMService.factory.ts` to include your new provider:
|
|
|
1469
1658
|
```typescript
|
|
1470
1659
|
import {
|
|
1471
1660
|
LLMProviders,
|
|
1472
|
-
|
|
1661
|
+
LLMServiceOptions,
|
|
1473
1662
|
YourProviderOptions,
|
|
1474
1663
|
} from './LLMService.typedefs';
|
|
1475
1664
|
import { YourProviderServiceFactory } from './providers/YourProvider';
|
|
@@ -1487,72 +1676,68 @@ export class LLMServiceFactory {
|
|
|
1487
1676
|
}
|
|
1488
1677
|
|
|
1489
1678
|
static getCompletionService<T extends LLMProviders>(
|
|
1490
|
-
|
|
1491
|
-
logger: Logger,
|
|
1492
|
-
options: any,
|
|
1679
|
+
serviceOptions: LLMServiceOptions<T>,
|
|
1493
1680
|
) {
|
|
1681
|
+
const { provider, options, logger } = serviceOptions;
|
|
1494
1682
|
switch (provider) {
|
|
1495
1683
|
// ... other providers
|
|
1496
1684
|
case LLMProviders.YourProvider:
|
|
1497
|
-
return YourProviderServiceFactory.createService(
|
|
1498
|
-
LLMPurposes.Completion,
|
|
1685
|
+
return YourProviderServiceFactory.createService({
|
|
1686
|
+
purpose: LLMPurposes.Completion,
|
|
1499
1687
|
logger,
|
|
1500
1688
|
options
|
|
1501
|
-
);
|
|
1689
|
+
});
|
|
1502
1690
|
default:
|
|
1503
1691
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
1504
1692
|
}
|
|
1505
1693
|
}
|
|
1506
1694
|
|
|
1507
1695
|
static getAssistanceService<T extends LLMProviders>(
|
|
1508
|
-
|
|
1509
|
-
logger: Logger,
|
|
1510
|
-
options: any,
|
|
1696
|
+
serviceOptions: LLMServiceOptions<T>,
|
|
1511
1697
|
) {
|
|
1698
|
+
const { provider, options, logger } = serviceOptions;
|
|
1512
1699
|
switch (provider) {
|
|
1513
1700
|
// ... other providers
|
|
1514
1701
|
case LLMProviders.YourProvider:
|
|
1515
|
-
return YourProviderServiceFactory.createService(
|
|
1516
|
-
LLMPurposes.Assistance,
|
|
1702
|
+
return YourProviderServiceFactory.createService({
|
|
1703
|
+
purpose: LLMPurposes.Assistance,
|
|
1517
1704
|
logger,
|
|
1518
1705
|
options
|
|
1519
|
-
);
|
|
1706
|
+
});
|
|
1520
1707
|
default:
|
|
1521
1708
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
1522
1709
|
}
|
|
1523
1710
|
}
|
|
1524
1711
|
|
|
1525
1712
|
static getSpeechToTextService<T extends LLMProviders>(
|
|
1526
|
-
|
|
1527
|
-
logger: Logger,
|
|
1528
|
-
options: any,
|
|
1713
|
+
serviceOptions: LLMServiceOptions<T>,
|
|
1529
1714
|
) {
|
|
1715
|
+
const { provider, options, logger } = serviceOptions;
|
|
1530
1716
|
switch (provider) {
|
|
1531
1717
|
// ... other providers
|
|
1532
1718
|
case LLMProviders.YourProvider:
|
|
1533
|
-
return YourProviderServiceFactory.createService(
|
|
1534
|
-
LLMPurposes.SpeechToText,
|
|
1719
|
+
return YourProviderServiceFactory.createService({
|
|
1720
|
+
purpose: LLMPurposes.SpeechToText,
|
|
1535
1721
|
logger,
|
|
1536
1722
|
options
|
|
1537
|
-
);
|
|
1723
|
+
});
|
|
1538
1724
|
default:
|
|
1539
1725
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
1540
1726
|
}
|
|
1541
1727
|
}
|
|
1542
1728
|
|
|
1543
1729
|
static getTextToSpeechService<T extends LLMProviders>(
|
|
1544
|
-
|
|
1545
|
-
logger: Logger,
|
|
1546
|
-
options: any,
|
|
1730
|
+
serviceOptions: LLMServiceOptions<T>,
|
|
1547
1731
|
) {
|
|
1732
|
+
const { provider, options, logger } = serviceOptions;
|
|
1548
1733
|
switch (provider) {
|
|
1549
1734
|
// ... other providers
|
|
1550
1735
|
case LLMProviders.YourProvider:
|
|
1551
|
-
return YourProviderServiceFactory.createService(
|
|
1552
|
-
LLMPurposes.TextToSpeech,
|
|
1736
|
+
return YourProviderServiceFactory.createService({
|
|
1737
|
+
purpose: LLMPurposes.TextToSpeech,
|
|
1553
1738
|
logger,
|
|
1554
1739
|
options
|
|
1555
|
-
);
|
|
1740
|
+
});
|
|
1556
1741
|
default:
|
|
1557
1742
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
1558
1743
|
}
|