@futdevpro/nts-dynamo 1.10.22 → 1.10.24
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/build/_modules/oauth2/_routes/oauth2.controller.d.ts +17 -0
- package/build/_modules/oauth2/_routes/oauth2.controller.d.ts.map +1 -0
- package/build/_modules/oauth2/_routes/oauth2.controller.js +97 -0
- package/build/_modules/oauth2/_routes/oauth2.controller.js.map +1 -0
- package/build/_modules/oauth2/_services/oauth2.auth-service.d.ts +31 -0
- package/build/_modules/oauth2/_services/oauth2.auth-service.d.ts.map +1 -0
- package/build/_modules/oauth2/_services/oauth2.auth-service.js +216 -0
- package/build/_modules/oauth2/_services/oauth2.auth-service.js.map +1 -0
- package/build/_modules/oauth2/_services/oauth2.control-service.d.ts +133 -0
- package/build/_modules/oauth2/_services/oauth2.control-service.d.ts.map +1 -0
- package/build/_modules/oauth2/_services/oauth2.control-service.js +574 -0
- package/build/_modules/oauth2/_services/oauth2.control-service.js.map +1 -0
- package/build/_modules/oauth2/index.d.ts +4 -0
- package/build/_modules/oauth2/index.d.ts.map +1 -0
- package/build/_modules/oauth2/index.js +7 -0
- package/build/_modules/oauth2/index.js.map +1 -0
- package/build/_modules/open-ai/_enums/open-ai-model.enum.d.ts +11 -0
- package/build/_modules/open-ai/_enums/open-ai-model.enum.d.ts.map +1 -0
- package/build/_modules/open-ai/_enums/open-ai-model.enum.js +110 -0
- package/build/_modules/open-ai/_enums/open-ai-model.enum.js.map +1 -0
- package/build/_modules/open-ai/_models/gpt-call-settings.interface.d.ts +54 -0
- package/build/_modules/open-ai/_models/gpt-call-settings.interface.d.ts.map +1 -0
- package/build/_modules/open-ai/_models/gpt-call-settings.interface.js +65 -0
- package/build/_modules/open-ai/_models/gpt-call-settings.interface.js.map +1 -0
- package/build/_modules/open-ai/_models/open-ai-api-env-settings.interface.d.ts +7 -0
- package/build/_modules/open-ai/_models/open-ai-api-env-settings.interface.d.ts.map +1 -0
- package/build/_modules/open-ai/_models/open-ai-api-env-settings.interface.js +3 -0
- package/build/_modules/open-ai/_models/open-ai-api-env-settings.interface.js.map +1 -0
- package/build/_modules/open-ai/_models/open-ai-settings.interface.d.ts +17 -0
- package/build/_modules/open-ai/_models/open-ai-settings.interface.d.ts.map +1 -0
- package/build/_modules/open-ai/_models/open-ai-settings.interface.js +25 -0
- package/build/_modules/open-ai/_models/open-ai-settings.interface.js.map +1 -0
- package/build/_modules/open-ai/_services/embedding.control-service.d.ts +26 -0
- package/build/_modules/open-ai/_services/embedding.control-service.d.ts.map +1 -0
- package/build/_modules/open-ai/_services/embedding.control-service.js +54 -0
- package/build/_modules/open-ai/_services/embedding.control-service.js.map +1 -0
- package/build/_modules/open-ai/_services/gpt.service-base.d.ts +98 -0
- package/build/_modules/open-ai/_services/gpt.service-base.d.ts.map +1 -0
- package/build/_modules/open-ai/_services/gpt.service-base.js +284 -0
- package/build/_modules/open-ai/_services/gpt.service-base.js.map +1 -0
- package/build/_modules/open-ai/_services/open-ai.service-base.d.ts +23 -0
- package/build/_modules/open-ai/_services/open-ai.service-base.d.ts.map +1 -0
- package/build/_modules/open-ai/_services/open-ai.service-base.js +50 -0
- package/build/_modules/open-ai/_services/open-ai.service-base.js.map +1 -0
- package/build/_modules/open-ai/index.d.ts +8 -0
- package/build/_modules/open-ai/index.d.ts.map +1 -0
- package/build/_modules/open-ai/index.js +11 -0
- package/build/_modules/open-ai/index.js.map +1 -0
- package/build/_modules/server/errors/errors.control-service.d.ts +9 -9
- package/build/_modules/server/errors/errors.control-service.d.ts.map +1 -1
- package/build/_modules/server/errors/errors.control-service.js.map +1 -1
- package/build/_modules/server/errors/errors.controller.d.ts.map +1 -1
- package/build/_modules/server/errors/errors.controller.js +14 -29
- package/build/_modules/server/errors/errors.controller.js.map +1 -1
- package/build/_modules/server/errors/errors.data-service.d.ts +8 -8
- package/build/_modules/server/errors/errors.data-service.d.ts.map +1 -1
- package/build/_modules/server/errors/errors.data-service.js +42 -12
- package/build/_modules/server/errors/errors.data-service.js.map +1 -1
- package/build/_services/base/db.service.d.ts +38 -0
- package/build/_services/base/db.service.d.ts.map +1 -1
- package/build/_services/base/db.service.js +40 -0
- package/build/_services/base/db.service.js.map +1 -1
- package/build/_services/server/app.server.d.ts +17 -0
- package/build/_services/server/app.server.d.ts.map +1 -1
- package/build/_services/server/app.server.js +17 -0
- package/build/_services/server/app.server.js.map +1 -1
- package/package.json +47 -17
- package/src/_modules/oauth2/_routes/oauth2.controller.ts +99 -0
- package/src/_modules/oauth2/_services/oauth2.auth-service.ts +232 -0
- package/src/_modules/oauth2/_services/oauth2.control-service.ts +651 -0
- package/src/_modules/oauth2/index.ts +9 -0
- package/src/_modules/open-ai/_enums/open-ai-model.enum.ts +137 -0
- package/src/_modules/open-ai/_models/gpt-call-settings.interface.ts +69 -0
- package/src/_modules/open-ai/_models/open-ai-api-env-settings.interface.ts +12 -0
- package/src/_modules/open-ai/_models/open-ai-settings.interface.ts +31 -0
- package/src/_modules/open-ai/_services/embedding.control-service.ts +61 -0
- package/src/_modules/open-ai/_services/gpt.service-base.ts +440 -0
- package/src/_modules/open-ai/_services/open-ai.service-base.ts +73 -0
- package/src/_modules/open-ai/index.ts +13 -0
- package/src/_modules/server/errors/errors.control-service.ts +9 -6
- package/src/_modules/server/errors/errors.controller.ts +19 -29
- package/src/_modules/server/errors/errors.data-service.ts +55 -12
- package/src/_services/base/db.service.ts +41 -0
- package/src/_services/server/app.server.ts +18 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
|
|
2
|
+
import { OpenAI, ClientOptions } from 'openai';
|
|
3
|
+
import { ChatCompletion, ChatCompletionMessageParam } from 'openai/resources';
|
|
4
|
+
|
|
5
|
+
import { DyFM_AnyError, DyFM_Error, DyFM_Error_Settings, DyFM_Log } from '@futdevpro/fsm-dynamo';
|
|
6
|
+
|
|
7
|
+
import { DyNTS_OpenAIModel } from '../_enums/open-ai-model.enum';
|
|
8
|
+
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
9
|
+
import { DyNTS_OpenAI_ServiceBase } from './open-ai.service-base';
|
|
10
|
+
import { DyNTS_GPTCall_Settings } from '../_models/gpt-call-settings.interface';
|
|
11
|
+
import { RequestOptions } from 'openai/core';
|
|
12
|
+
import { ChatCompletionCreateParamsBase } from 'openai/resources/chat/completions';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* {
|
|
16
|
+
organization: 'org-XY',
|
|
17
|
+
apiKey: 'sk-XY',
|
|
18
|
+
project: 'proj_XY',
|
|
19
|
+
}
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Di Dictionary DiModel DiEz DiAz
|
|
23
|
+
|
|
24
|
+
export class DyNTS_GPT_ServiceBase extends DyNTS_OpenAI_ServiceBase {
|
|
25
|
+
|
|
26
|
+
defaultLogReplacer: string = '...';
|
|
27
|
+
|
|
28
|
+
async askYesNoQuestion(
|
|
29
|
+
question: string,
|
|
30
|
+
issuer: string,
|
|
31
|
+
replaceThisInLog?: string
|
|
32
|
+
): Promise<boolean> {
|
|
33
|
+
question += ' (Only answer with "Yes" or "No")';
|
|
34
|
+
|
|
35
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
36
|
+
|
|
37
|
+
const answer = await this.getQuestionAnswer(question, issuer);
|
|
38
|
+
|
|
39
|
+
return answer.toUpperCase().includes('YES');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async askSimpleQuestion(
|
|
43
|
+
question: string,
|
|
44
|
+
issuer: string,
|
|
45
|
+
replaceThisInLog?: string
|
|
46
|
+
): Promise<string> {
|
|
47
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
48
|
+
|
|
49
|
+
return await this.getQuestionAnswer(question, issuer);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async askPercentageQuestion(
|
|
53
|
+
question: string,
|
|
54
|
+
issuer: string,
|
|
55
|
+
replaceThisInLog?: string
|
|
56
|
+
): Promise<number> {
|
|
57
|
+
question += ' (Only answer with a number between 0 and 1, e.g.: 0.65)';
|
|
58
|
+
|
|
59
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
60
|
+
|
|
61
|
+
const answer = await this.getQuestionAnswer(question, issuer);
|
|
62
|
+
|
|
63
|
+
if (isNaN(+answer)) {
|
|
64
|
+
DyFM_Log.error('GPT_ServiceBase', 'asykPercentageQuestion', 'Invalid answer', {
|
|
65
|
+
question,
|
|
66
|
+
answer,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return +answer;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async askSelectQuestion(
|
|
76
|
+
question: string,
|
|
77
|
+
selectFrom: string[],
|
|
78
|
+
issuer: string,
|
|
79
|
+
replaceThisInLog?: string
|
|
80
|
+
): Promise<string> {
|
|
81
|
+
question += ` (Only answer with one of the following: ${this.getListAsText(selectFrom)})`;
|
|
82
|
+
|
|
83
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
84
|
+
|
|
85
|
+
let answer = await this.getQuestionAnswer(question, issuer);
|
|
86
|
+
|
|
87
|
+
answer = answer.toLocaleUpperCase();
|
|
88
|
+
|
|
89
|
+
for (const item of selectFrom) {
|
|
90
|
+
if (answer.includes(item.toLocaleUpperCase())) return item;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async askMultipleSelectQuestionWithOptions(
|
|
97
|
+
question: string,
|
|
98
|
+
options: string[],
|
|
99
|
+
issuer: string,
|
|
100
|
+
replaceThisInLog?: string
|
|
101
|
+
): Promise<string[]> {
|
|
102
|
+
question += (` (You can choose one or more of the following: ${this.getListAsText(options)})`);
|
|
103
|
+
|
|
104
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
105
|
+
|
|
106
|
+
let answer = await this.getQuestionAnswer(question, issuer);
|
|
107
|
+
|
|
108
|
+
answer = answer.toLocaleUpperCase();
|
|
109
|
+
|
|
110
|
+
const result: string[] = [];
|
|
111
|
+
|
|
112
|
+
for (const item of options) {
|
|
113
|
+
if (answer.includes(item.toLocaleUpperCase())) {
|
|
114
|
+
result.push(item);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Azt kérjük tőle, hogy adjon egy JSON formában választ.
|
|
123
|
+
* Amit aztán megpróbálunk JSON.parse-olni.
|
|
124
|
+
* Ha nem sikerül, akkor { unparsable: answer }-t adunk vissza.
|
|
125
|
+
*/
|
|
126
|
+
async askJSONQuestion(
|
|
127
|
+
question: string,
|
|
128
|
+
issuer: string,
|
|
129
|
+
replaceThisInLog?: string
|
|
130
|
+
): Promise<any> {
|
|
131
|
+
question += ' (The answer must be in JSON format)';
|
|
132
|
+
|
|
133
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
134
|
+
|
|
135
|
+
const answer = await this.getQuestionAnswer(question, issuer);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
// replace all ```json, ```, \n
|
|
139
|
+
return JSON.parse(
|
|
140
|
+
answer.replaceAll('```json', '').replaceAll('```', '').replaceAll('\n', '')
|
|
141
|
+
);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
return {
|
|
144
|
+
unparsable: answer,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Azt kérjük tőle, hogy adjon egy JSON formában választ.
|
|
151
|
+
* Amit aztán megpróbálunk JSON.parse-olni.
|
|
152
|
+
* Ha nem sikerül, akkor { unparsable: answer }-t adunk vissza.
|
|
153
|
+
*
|
|
154
|
+
* A keysDescription-be leírjuk, milyen kulcsokat várunk. (nem konkrét kulcsneveket)
|
|
155
|
+
*/
|
|
156
|
+
async askJSONQuestionWithKeysDescription(
|
|
157
|
+
question: string,
|
|
158
|
+
keysDescription: string,
|
|
159
|
+
issuer: string,
|
|
160
|
+
replaceThisInLog?: string
|
|
161
|
+
): Promise<any> {
|
|
162
|
+
question += ` (The answer must be in JSON format, ${keysDescription})`;
|
|
163
|
+
|
|
164
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
165
|
+
|
|
166
|
+
const answer = await this.getQuestionAnswer(question, issuer);
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
// replace all ```json, ```, \n
|
|
170
|
+
return JSON.parse(
|
|
171
|
+
answer.replaceAll('```json', '').replaceAll('```', '').replaceAll('\n', '')
|
|
172
|
+
);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
return {
|
|
175
|
+
unparsable: answer,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Azt kérjük tőle, hogy adjon egy JSON formában választ.
|
|
182
|
+
* Amit aztán megpróbálunk JSON.parse-olni.
|
|
183
|
+
* Ha nem sikerül, akkor { unparsable: answer }-t adunk vissza.
|
|
184
|
+
*
|
|
185
|
+
* A keys-be leírjuk a konkrét kulcsneveket.
|
|
186
|
+
*/
|
|
187
|
+
async askJSONQuestionWithExactKeys(
|
|
188
|
+
question: string,
|
|
189
|
+
keys: string[],
|
|
190
|
+
issuer: string,
|
|
191
|
+
replaceThisInLog?: string
|
|
192
|
+
): Promise<any> {
|
|
193
|
+
question += ` (The answer must be in JSON format, ` +
|
|
194
|
+
`where the keys are: ${this.getListAsText(keys)})`;
|
|
195
|
+
|
|
196
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
197
|
+
|
|
198
|
+
const answer = await this.getQuestionAnswer(question, issuer);
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
// replace all ```json, ```, \n
|
|
202
|
+
return JSON.parse(
|
|
203
|
+
answer.replaceAll('```json', '').replaceAll('```', '').replaceAll('\n', '')
|
|
204
|
+
);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
return {
|
|
207
|
+
unparsable: answer,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async askListQuestion(
|
|
213
|
+
question: string,
|
|
214
|
+
issuer: string,
|
|
215
|
+
replaceThisInLog?: string
|
|
216
|
+
): Promise<string[]> {
|
|
217
|
+
question += ' (The answer must be in JSON format, a list of strings)';
|
|
218
|
+
|
|
219
|
+
this.logQuestion(question, issuer, replaceThisInLog);
|
|
220
|
+
|
|
221
|
+
const answer = await this.getQuestionAnswer(question, issuer);
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const parsed = JSON.parse(
|
|
225
|
+
answer.replaceAll('```json', '').replaceAll('```', '').replaceAll('\n', '')
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
if (Array.isArray(parsed)) {
|
|
229
|
+
return parsed;
|
|
230
|
+
} else if (typeof parsed === 'object') {
|
|
231
|
+
return Object.values(parsed);
|
|
232
|
+
} else {
|
|
233
|
+
DyFM_Log.error('GPT_ServiceBase', 'askListQuestion', 'Invalid answer', {
|
|
234
|
+
question,
|
|
235
|
+
answer,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
return [ parsed ];
|
|
239
|
+
}
|
|
240
|
+
} catch (error) {
|
|
241
|
+
return answer.split('\n').filter(item => item);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private logQuestion(question: string, issuer: string, replaceThisInLog?: string): void {
|
|
246
|
+
if (this.debugLog) {
|
|
247
|
+
if (replaceThisInLog) {
|
|
248
|
+
question = question.replace(replaceThisInLog, this.defaultLogReplacer);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
console.log('\n - ', question);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* This function will log the answer if the debugLog is true
|
|
257
|
+
*/
|
|
258
|
+
async getQuestionAnswer(
|
|
259
|
+
question: string,
|
|
260
|
+
issuer: string,
|
|
261
|
+
messageSettings: DyNTS_GPTCall_Settings = this.defaultSettings
|
|
262
|
+
): Promise<string> {
|
|
263
|
+
const answer = await this.resolveSimpleUserMessage(question, issuer, messageSettings);
|
|
264
|
+
|
|
265
|
+
console.log(' - ', answer);
|
|
266
|
+
|
|
267
|
+
return answer;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* olvasható mondatszerű-listaszerű formába teszi a listaelemeket
|
|
272
|
+
* pl.: ['a', 'b', 'c'] -> '"a", "b" or "c"'
|
|
273
|
+
*/
|
|
274
|
+
getListAsText(list: string[]): string {
|
|
275
|
+
list = list.filter(item => item?.trim()).map(item => `"${item}"`);
|
|
276
|
+
|
|
277
|
+
/* list = list.map(item => item.toLocaleLowerCase()); */
|
|
278
|
+
|
|
279
|
+
list.push(list.pop() + ' or ' + list.pop());
|
|
280
|
+
|
|
281
|
+
return list.join(', ');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* This function will log the question and the answer if the debugLog is true
|
|
286
|
+
*/
|
|
287
|
+
async getAnswer(
|
|
288
|
+
question: string,
|
|
289
|
+
issuer: string,
|
|
290
|
+
settings?: DyNTS_GPTCall_Settings
|
|
291
|
+
): Promise<string> {
|
|
292
|
+
if (this.debugLog) {
|
|
293
|
+
console.log('\n - ', question);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const answer = await this.resolveSimpleUserMessage(question, issuer, settings);
|
|
297
|
+
|
|
298
|
+
if (this.debugLog) {
|
|
299
|
+
console.log(' - ', answer);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return answer;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async resolveSimpleUserMessage(
|
|
306
|
+
message: string,
|
|
307
|
+
issuer: string,
|
|
308
|
+
settings?: DyNTS_GPTCall_Settings
|
|
309
|
+
): Promise<string> {
|
|
310
|
+
return this.resolveConversation(
|
|
311
|
+
[{ role: 'user', content: message }],
|
|
312
|
+
issuer,
|
|
313
|
+
settings,
|
|
314
|
+
false
|
|
315
|
+
) as Promise<string>;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async resolveConversation(
|
|
319
|
+
conversation: DyNTS_GPT_Message[],
|
|
320
|
+
issuer: string,
|
|
321
|
+
settings?: DyNTS_GPTCall_Settings,
|
|
322
|
+
getFullResponse?: boolean
|
|
323
|
+
): Promise<string | ChatCompletion> {
|
|
324
|
+
try {
|
|
325
|
+
const result: ChatCompletion = await this.openai.chat.completions.create(
|
|
326
|
+
this.getMessageCreateInput(conversation, issuer, settings)
|
|
327
|
+
) as ChatCompletion;
|
|
328
|
+
|
|
329
|
+
if (getFullResponse) {
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return result.choices[0].message.content;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
throw new DyFM_Error({
|
|
336
|
+
...this.getDefaultErrorSettings('resolveConversation', error, issuer),
|
|
337
|
+
|
|
338
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-OAB-RC0`,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* TODO: Overview this: maybe it should use each setting from default if not provided here
|
|
345
|
+
*/
|
|
346
|
+
private getMessageCreateInput(
|
|
347
|
+
messages: DyNTS_GPT_Message[],
|
|
348
|
+
issuer: string,
|
|
349
|
+
settings: DyNTS_GPTCall_Settings = this.defaultSettings
|
|
350
|
+
): ChatCompletionCreateParamsBase {
|
|
351
|
+
try {
|
|
352
|
+
messages.unshift(this.getDefaultSystemMessage(settings));
|
|
353
|
+
|
|
354
|
+
const result: ChatCompletionCreateParamsBase = {
|
|
355
|
+
model: settings.useModel ?? this.defaultModel,
|
|
356
|
+
messages: messages as ChatCompletionMessageParam[],
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
if (DyFM_notNull(settings.temperature)) {
|
|
360
|
+
result.temperature = settings.temperature;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (DyFM_notNull(settings.maxTokens)) {
|
|
364
|
+
result.max_tokens = settings.maxTokens;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (DyFM_notNull(settings.topP)) {
|
|
368
|
+
result.top_p = settings.topP;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (DyFM_notNull(settings.frequencyPenalty)) {
|
|
372
|
+
result.frequency_penalty = settings.frequencyPenalty;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (DyFM_notNull(settings.presencePenalty)) {
|
|
376
|
+
result.presence_penalty = settings.presencePenalty;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return result;
|
|
380
|
+
} catch (error) {
|
|
381
|
+
throw new DyFM_Error({
|
|
382
|
+
...this.getDefaultErrorSettings('getMessageCreateSettings', error, issuer),
|
|
383
|
+
|
|
384
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-OAB-RC0`,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
private getDefaultSystemMessage(settings: DyNTS_GPTCall_Settings): DyNTS_GPT_Message {
|
|
390
|
+
return {
|
|
391
|
+
role: DyNTS_GPT_Message_Role.system,
|
|
392
|
+
content: settings.systemPrompt || this.defaultSystemPrompt,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export interface DyNTS_GPT_Message {
|
|
398
|
+
role: DyNTS_GPT_Message_Role | string;
|
|
399
|
+
content: string;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export enum DyNTS_GPT_Message_Role {
|
|
403
|
+
/**
|
|
404
|
+
* Developer-provided instructions that the model should follow, regardless of
|
|
405
|
+
* messages sent by the user. With o1 models and newer, `developer` messages
|
|
406
|
+
* replace the previous `system` messages.
|
|
407
|
+
*/
|
|
408
|
+
developer = 'developer',
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Developer-provided instructions that the model should follow, regardless of
|
|
412
|
+
* messages sent by the user. With o1 models and newer, use `developer` messages
|
|
413
|
+
* for this purpose instead.
|
|
414
|
+
*/
|
|
415
|
+
system = 'system',
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Messages sent by an end user, containing prompts or additional context
|
|
419
|
+
* information.
|
|
420
|
+
*/
|
|
421
|
+
user = 'user',
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Messages sent by the model in response to user messages.
|
|
425
|
+
*/
|
|
426
|
+
assistant = 'assistant',
|
|
427
|
+
|
|
428
|
+
/** ??? */
|
|
429
|
+
tool = 'tool',
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* ???
|
|
433
|
+
* @deprecated
|
|
434
|
+
*/
|
|
435
|
+
function = 'function',
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export function DyFM_notNull(value: any): boolean {
|
|
439
|
+
return value !== null && value !== undefined;
|
|
440
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
|
|
2
|
+
import { OpenAI, ClientOptions } from 'openai';
|
|
3
|
+
import { ChatCompletion, ChatCompletionMessageParam } from 'openai/resources';
|
|
4
|
+
|
|
5
|
+
import { DyFM_AnyError, DyFM_Error, DyFM_Error_Settings, DyFM_Log } from '@futdevpro/fsm-dynamo';
|
|
6
|
+
|
|
7
|
+
import { DyNTS_OpenAIModel } from '../_enums/open-ai-model.enum';
|
|
8
|
+
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
9
|
+
import { DyNTS_OpenAI_Settings } from '../_models/open-ai-settings.interface';
|
|
10
|
+
import { DyNTS_GPTCall_Settings } from '../_models/gpt-call-settings.interface';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* {
|
|
15
|
+
* organization: 'org-XY',
|
|
16
|
+
* apiKey: 'sk-XY',
|
|
17
|
+
* project: 'proj_XY',
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Di Dictionary DiModel DiEz DiAz
|
|
22
|
+
|
|
23
|
+
export class DyNTS_OpenAI_ServiceBase {
|
|
24
|
+
|
|
25
|
+
readonly defaultErrorUserMsg: string =
|
|
26
|
+
`We encountered an unhandled Control Service Error, ` +
|
|
27
|
+
`\nplease contact the responsible development team.`;
|
|
28
|
+
|
|
29
|
+
readonly openai: OpenAI;
|
|
30
|
+
|
|
31
|
+
/* readonly defaultSystemPrompt: string;
|
|
32
|
+
readonly defaultModel: DyNTS_OpenAIModel | string; */
|
|
33
|
+
readonly defaultSettings: DyNTS_GPTCall_Settings;
|
|
34
|
+
|
|
35
|
+
get debugLog(): boolean {
|
|
36
|
+
return this.defaultSettings.debugLog;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get defaultSystemPrompt(): string {
|
|
40
|
+
return this.defaultSettings.systemPrompt;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get defaultModel(): DyNTS_OpenAIModel | string {
|
|
44
|
+
return this.defaultSettings.useModel;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
set: DyNTS_OpenAI_Settings
|
|
49
|
+
) {
|
|
50
|
+
this.openai = new OpenAI(set.openAIConfig);
|
|
51
|
+
this.defaultSettings = set.defaultSettings ?? new DyNTS_GPTCall_Settings();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected getDefaultErrorSettings(
|
|
55
|
+
fnName: string,
|
|
56
|
+
error: DyFM_AnyError,
|
|
57
|
+
issuer: string
|
|
58
|
+
): DyFM_Error_Settings {
|
|
59
|
+
return {
|
|
60
|
+
status: (error as DyFM_Error)?.___status ?? 500,
|
|
61
|
+
message: (error as Error)?.message ??
|
|
62
|
+
(error as DyFM_Error)?._message ??
|
|
63
|
+
`${fnName} was UNSUCCESSFUL (${DyNTS_global_settings.systemShortCodeName})`,
|
|
64
|
+
addECToUserMsg: !(error as DyFM_Error)?.__userMessage,
|
|
65
|
+
userMessage: (error as DyFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
|
|
66
|
+
issuer: issuer,
|
|
67
|
+
issuerService: this.constructor?.name,
|
|
68
|
+
error: error,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export * from './_enums/open-ai-model.enum';
|
|
4
|
+
|
|
5
|
+
export * from './_models/gpt-call-settings.interface';
|
|
6
|
+
export * from './_models/open-ai-api-env-settings.interface';
|
|
7
|
+
export * from './_models/open-ai-settings.interface';
|
|
8
|
+
|
|
9
|
+
export * from './_services/embedding.control-service';
|
|
10
|
+
export * from './_services/gpt.service-base';
|
|
11
|
+
export * from './_services/open-ai.service-base';
|
|
12
|
+
|
|
13
|
+
|
|
@@ -25,7 +25,7 @@ export abstract class DyNTS_Errors_ControlService<
|
|
|
25
25
|
readonly version: string = DyNTS_global_settings.systemVersion;
|
|
26
26
|
duplicationCounter: number;
|
|
27
27
|
|
|
28
|
-
abstract recordError(data
|
|
28
|
+
abstract recordError(data: T_Errors, issuer: string, alwaysRecord?: boolean): Promise<void>;
|
|
29
29
|
|
|
30
30
|
abstract handleInternalError(
|
|
31
31
|
error: DyFM_AnyError | any,
|
|
@@ -33,34 +33,37 @@ export abstract class DyNTS_Errors_ControlService<
|
|
|
33
33
|
alwaysRecord?: boolean,
|
|
34
34
|
): Promise<void>;
|
|
35
35
|
|
|
36
|
-
abstract checkErrorIsStringifyableOrResolvable(error: T_Error): T_Error | 'UNRESOLVABLE';
|
|
36
|
+
abstract checkErrorIsStringifyableOrResolvable(error: T_Error, issuer: string): T_Error | 'UNRESOLVABLE';
|
|
37
37
|
|
|
38
|
-
abstract getPriorityMultiplierByLevel(level: DyFM_ErrorLevel): number;
|
|
38
|
+
abstract getPriorityMultiplierByLevel(level: DyFM_ErrorLevel, issuer: string): number;
|
|
39
39
|
|
|
40
40
|
abstract getErrorsFromDate(
|
|
41
41
|
date: Date,
|
|
42
42
|
issuer: string,
|
|
43
43
|
): Promise<DyFM_Paged<T_Errors>>;
|
|
44
44
|
|
|
45
|
-
abstract deleteError(errorId: string, alwaysDelete?: boolean): Promise<void>;
|
|
45
|
+
abstract deleteError(errorId: string, issuer: string, alwaysDelete?: boolean): Promise<void>;
|
|
46
46
|
|
|
47
|
-
abstract deleteAllErrors(alwaysDelete?: boolean): Promise<void>;
|
|
47
|
+
abstract deleteAllErrors(issuer: string, alwaysDelete?: boolean): Promise<void>;
|
|
48
48
|
|
|
49
|
-
abstract getErrorsInRange(range: DyFM_RelativeDate): Promise<DyFM_Paged<T_Errors>>;
|
|
49
|
+
abstract getErrorsInRange(range: DyFM_RelativeDate, issuer: string): Promise<DyFM_Paged<T_Errors>>;
|
|
50
50
|
|
|
51
51
|
abstract getErrorsPaged(
|
|
52
52
|
range: DyFM_RelativeDate,
|
|
53
53
|
pageSize: number,
|
|
54
54
|
pageIndex: number,
|
|
55
|
+
issuer: string,
|
|
55
56
|
): Promise<DyFM_Paged<T_Errors>>;
|
|
56
57
|
|
|
57
58
|
abstract getLastErrors(
|
|
58
59
|
range: DyFM_RelativeDate,
|
|
59
60
|
pageSize: number,
|
|
60
61
|
pageIndex: number,
|
|
62
|
+
issuer: string,
|
|
61
63
|
): Promise<DyFM_Paged<T_Errors>>;
|
|
62
64
|
|
|
63
65
|
abstract searchErrors(
|
|
64
66
|
searchQuery: DyFM_SearchQuery<T_Errors>,
|
|
67
|
+
issuer: string,
|
|
65
68
|
): Promise<DyFM_SearchResult<T_Errors>>;
|
|
66
69
|
}
|
|
@@ -71,12 +71,9 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
71
71
|
endpoint: '/error/log',
|
|
72
72
|
tasks: [
|
|
73
73
|
async (req: Request, res: Response, issuer?: string): Promise<void> => {
|
|
74
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
75
|
-
data: req.body,
|
|
76
|
-
issuer: issuer ?? req.body?.issuer ?? 'unknown-client',
|
|
77
|
-
});
|
|
74
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
78
75
|
|
|
79
|
-
await error_CS.recordError();
|
|
76
|
+
await error_CS.recordError(req.body, issuer ?? 'unknown-issuer');
|
|
80
77
|
|
|
81
78
|
res.send({
|
|
82
79
|
result: 'error logged',
|
|
@@ -91,11 +88,9 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
91
88
|
endpoint: '/error/mark-done/:errorId',
|
|
92
89
|
tasks: [
|
|
93
90
|
async (req: Request, res: Response, issuer?: string): Promise<void> => {
|
|
94
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
95
|
-
issuer: issuer,
|
|
96
|
-
});
|
|
91
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
97
92
|
|
|
98
|
-
await error_CS.deleteError(req.params.errorId, true);
|
|
93
|
+
await error_CS.deleteError(req.params.errorId, issuer ?? 'unknown-issuer', true);
|
|
99
94
|
|
|
100
95
|
res.send({
|
|
101
96
|
result: 'error deleted',
|
|
@@ -110,11 +105,9 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
110
105
|
endpoint: '/error/mark-all-done',
|
|
111
106
|
tasks: [
|
|
112
107
|
async (req: Request, res: Response, issuer?: string): Promise<void> => {
|
|
113
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
114
|
-
issuer: issuer,
|
|
115
|
-
});
|
|
108
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
116
109
|
|
|
117
|
-
await error_CS.deleteAllErrors(true);
|
|
110
|
+
await error_CS.deleteAllErrors(issuer ?? 'unknown-issuer', true);
|
|
118
111
|
|
|
119
112
|
res.send({
|
|
120
113
|
result: 'all error deleted',
|
|
@@ -149,12 +142,13 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
149
142
|
endpoint: '/error/get-range/:range',
|
|
150
143
|
tasks: [
|
|
151
144
|
async (req: Request, res: Response, issuer: string) : Promise<void> => {
|
|
152
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
153
|
-
issuer: issuer,
|
|
154
|
-
});
|
|
145
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
155
146
|
|
|
156
147
|
res.send(
|
|
157
|
-
await error_CS.getErrorsInRange(
|
|
148
|
+
await error_CS.getErrorsInRange(
|
|
149
|
+
req.params.range as DyFM_RelativeDate,
|
|
150
|
+
issuer ?? 'unknown-issuer'
|
|
151
|
+
)
|
|
158
152
|
);
|
|
159
153
|
},
|
|
160
154
|
],
|
|
@@ -166,9 +160,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
166
160
|
endpoint: '/error/get-paged/:range/:pageSize/:pageIndex',
|
|
167
161
|
tasks: [
|
|
168
162
|
async (req: Request, res: Response, issuer: string) : Promise<void> => {
|
|
169
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
170
|
-
issuer: issuer,
|
|
171
|
-
});
|
|
163
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
172
164
|
|
|
173
165
|
let pageSize: number = req.params.pageSize ? +req.params.pageSize : 30;
|
|
174
166
|
let pageIndex: number = req.params.pageIndex ? +req.params.pageIndex : 0;
|
|
@@ -183,7 +175,8 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
183
175
|
await error_CS.getErrorsPaged(
|
|
184
176
|
req.params.range as DyFM_RelativeDate,
|
|
185
177
|
pageSize,
|
|
186
|
-
pageIndex
|
|
178
|
+
pageIndex,
|
|
179
|
+
issuer ?? 'unknown-issuer'
|
|
187
180
|
)
|
|
188
181
|
);
|
|
189
182
|
},
|
|
@@ -196,9 +189,7 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
196
189
|
endpoint: '/error/get-last-paged/:range/:pageSize/:pageIndex',
|
|
197
190
|
tasks: [
|
|
198
191
|
async (req: Request, res: Response, issuer: string) : Promise<void> => {
|
|
199
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
200
|
-
issuer: issuer,
|
|
201
|
-
});
|
|
192
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
202
193
|
|
|
203
194
|
let pageSize: number = req.params.pageSize ? +req.params.pageSize : 30;
|
|
204
195
|
let pageIndex: number = req.params.pageIndex ? +req.params.pageIndex : 0;
|
|
@@ -213,7 +204,8 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
213
204
|
await error_CS.getLastErrors(
|
|
214
205
|
req.params.range as DyFM_RelativeDate,
|
|
215
206
|
pageSize,
|
|
216
|
-
pageIndex
|
|
207
|
+
pageIndex,
|
|
208
|
+
issuer ?? 'unknown-issuer'
|
|
217
209
|
)
|
|
218
210
|
);
|
|
219
211
|
},
|
|
@@ -226,12 +218,10 @@ export abstract class DyNTS_Errors_Controller<
|
|
|
226
218
|
endpoint: '/error/search',
|
|
227
219
|
tasks: [
|
|
228
220
|
async (req: Request, res: Response, issuer: string) : Promise<void> => {
|
|
229
|
-
const error_CS: T_Error_ControlService = this.getError_ControlService(
|
|
230
|
-
issuer: issuer,
|
|
231
|
-
});
|
|
221
|
+
const error_CS: T_Error_ControlService = this.getError_ControlService();
|
|
232
222
|
|
|
233
223
|
res.send(
|
|
234
|
-
await error_CS.searchErrors(req.body)
|
|
224
|
+
await error_CS.searchErrors(req.body, issuer ?? 'unknown-issuer')
|
|
235
225
|
);
|
|
236
226
|
},
|
|
237
227
|
],
|