@tiledesk/tiledesk-tybot-connector 2.0.33 → 2.0.34
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/package.json
CHANGED
|
@@ -30,11 +30,6 @@ class DirAskGPTV2 {
|
|
|
30
30
|
|
|
31
31
|
this.intentDir = new DirIntent(context);
|
|
32
32
|
this.logger = new Logger({ request_id: this.requestId, dev: this.context.supportRequest?.draft, intent_id: this.context.reply?.attributes?.intent_info?.intent_id });
|
|
33
|
-
|
|
34
|
-
this.rerankingOff = false;
|
|
35
|
-
if (process.env.RERANKING_OFF && (process.env.RERANKING_OFF === "true" || process.env.RERANKING_OFF === true)) {
|
|
36
|
-
this.rerankingOff = true;
|
|
37
|
-
}
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
execute(directive, callback) {
|
|
@@ -63,7 +58,6 @@ class DirAskGPTV2 {
|
|
|
63
58
|
return;
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
let publicKey = false;
|
|
67
61
|
let trueIntent = action.trueIntent;
|
|
68
62
|
let falseIntent = action.falseIntent;
|
|
69
63
|
let trueIntentAttributes = action.trueIntentAttributes;
|
|
@@ -74,11 +68,11 @@ class DirAskGPTV2 {
|
|
|
74
68
|
winston.debug("DirAskGPTV2 trueIntentAttributes", trueIntentAttributes)
|
|
75
69
|
winston.debug("DirAskGPTV2 falseIntentAttributes", falseIntentAttributes)
|
|
76
70
|
|
|
77
|
-
|
|
78
71
|
// default values
|
|
79
72
|
let answer = "No answers";
|
|
80
73
|
let namespace = this.context.projectId;
|
|
81
|
-
let
|
|
74
|
+
let llm;
|
|
75
|
+
let model;
|
|
82
76
|
let temperature;
|
|
83
77
|
let max_tokens;
|
|
84
78
|
let top_k;
|
|
@@ -87,7 +81,8 @@ class DirAskGPTV2 {
|
|
|
87
81
|
let citations = false;
|
|
88
82
|
let chunks_only = false;
|
|
89
83
|
let engine;
|
|
90
|
-
|
|
84
|
+
let reranking;
|
|
85
|
+
let skip_unanswered;
|
|
91
86
|
|
|
92
87
|
let contexts = {
|
|
93
88
|
"gpt-3.5-turbo": "You are an helpful assistant for question-answering tasks.\nUse ONLY the pieces of retrieved context delimited by #### to answer the question.\nIf you don't know the answer, just say: \"I don't know<NOANS>\"\n\n####{context}####",
|
|
@@ -105,16 +100,18 @@ class DirAskGPTV2 {
|
|
|
105
100
|
|
|
106
101
|
let source = null;
|
|
107
102
|
|
|
108
|
-
|
|
109
|
-
this.logger.error(
|
|
110
|
-
|
|
103
|
+
await this.checkMandatoryParameters(action).catch( async (missing_param) => {
|
|
104
|
+
this.logger.error(`[Ask Knowledge Base] missing attribute '${missing_param}'`);
|
|
105
|
+
await this.chatbot.addParameter("flowError", `AskKnowledgeBase Error: '${missing_param}' attribute is undefined`);
|
|
111
106
|
await this.#assignAttributes(action, answer, source);
|
|
112
107
|
if (falseIntent) {
|
|
113
108
|
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
109
|
+
callback(true);
|
|
110
|
+
return Promise.reject();
|
|
114
111
|
}
|
|
115
|
-
callback(
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
112
|
+
callback();
|
|
113
|
+
return Promise.reject();
|
|
114
|
+
})
|
|
118
115
|
|
|
119
116
|
if (action.namespace) {
|
|
120
117
|
namespace = action.namespace;
|
|
@@ -122,30 +119,27 @@ class DirAskGPTV2 {
|
|
|
122
119
|
if (action.model) {
|
|
123
120
|
model = action.model;
|
|
124
121
|
}
|
|
125
|
-
|
|
126
122
|
if (action.top_k) {
|
|
127
123
|
top_k = action.top_k;
|
|
128
124
|
}
|
|
129
|
-
|
|
130
125
|
if (action.temperature) {
|
|
131
126
|
temperature = action.temperature;
|
|
132
127
|
}
|
|
133
|
-
|
|
134
128
|
if (action.max_tokens) {
|
|
135
129
|
max_tokens = action.max_tokens;
|
|
136
130
|
}
|
|
137
|
-
|
|
138
131
|
if (action.alpha) {
|
|
139
132
|
alpha = action.alpha;
|
|
140
133
|
}
|
|
141
|
-
|
|
142
134
|
if (action.citations) {
|
|
143
135
|
citations = action.citations;
|
|
144
136
|
}
|
|
145
|
-
|
|
146
137
|
if (action.chunks_only) {
|
|
147
138
|
chunks_only = action.chunks_only;
|
|
148
139
|
}
|
|
140
|
+
if (action.reranking) {
|
|
141
|
+
reranking = action.reranking;
|
|
142
|
+
}
|
|
149
143
|
|
|
150
144
|
let requestVariables = null;
|
|
151
145
|
requestVariables =
|
|
@@ -175,41 +169,67 @@ class DirAskGPTV2 {
|
|
|
175
169
|
}
|
|
176
170
|
}
|
|
177
171
|
|
|
178
|
-
let key
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
172
|
+
let key;
|
|
173
|
+
let publicKey = false;
|
|
174
|
+
let ollama_integration;
|
|
175
|
+
|
|
176
|
+
if (action.llm === 'ollama') {
|
|
177
|
+
ollama_integration = await integrationService.getIntegration(this.projectId, action.llm, this.token).catch( async (err) => {
|
|
178
|
+
this.logger.error("[Ask Knowledge Base] Error getting ollama integration.");
|
|
179
|
+
await this.chatbot.addParameter("flowError", "Ollama integration not found");
|
|
180
|
+
if (falseIntent) {
|
|
181
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
182
|
+
callback(true);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
callback();
|
|
186
|
+
return;
|
|
187
|
+
})
|
|
189
188
|
} else {
|
|
190
|
-
|
|
191
|
-
}
|
|
189
|
+
key = await integrationService.getKeyFromIntegrations(this.projectId, action.llm, this.token);
|
|
192
190
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
191
|
+
if (!key && action.llm === 'openai') {
|
|
192
|
+
this.logger.native("[Ask Knowledge Base] OpenAI key not found in Integration. Retrieve shared OpenAI key.");
|
|
193
|
+
key = process.env.GPTKEY;
|
|
194
|
+
publicKey = true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!key) {
|
|
198
|
+
this.logger.error(`[Ask Knowledge Base] llm key for ${action.llm} not found in integrations`);
|
|
199
|
+
await this.chatbot.addParameter("flowError", `AskKnowledgeBase Error: missing key for llm ${action.llm}`);
|
|
200
|
+
if (falseIntent) {
|
|
201
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
202
|
+
callback(true);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
callback();
|
|
199
206
|
return;
|
|
200
207
|
}
|
|
201
|
-
callback();
|
|
202
|
-
return;
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
if (publicKey === true && !chunks_only) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
try {
|
|
212
|
+
let keep_going = await quotasService.checkQuoteAvailability(this.projectId, this.token)
|
|
213
|
+
if (keep_going === false) {
|
|
214
|
+
this.logger.warn("[AI Prompt] OpenAI tokens quota exceeded");
|
|
215
|
+
await this.chatbot.addParameter("flowError", "GPT Error: tokens quota exceeded");
|
|
216
|
+
if (falseIntent) {
|
|
217
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
218
|
+
callback();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
callback();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
} catch (err) {
|
|
225
|
+
this.logger.error("An error occured on checking token quota availability");
|
|
226
|
+
await this.chatbot.addParameter("flowError", "An error occured on checking token quota availability");
|
|
227
|
+
if (falseIntent) {
|
|
228
|
+
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
229
|
+
callback();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
callback();
|
|
213
233
|
return;
|
|
214
234
|
}
|
|
215
235
|
}
|
|
@@ -262,6 +282,7 @@ class DirAskGPTV2 {
|
|
|
262
282
|
question: filled_question,
|
|
263
283
|
gptkey: key,
|
|
264
284
|
namespace: namespace,
|
|
285
|
+
llm: llm,
|
|
265
286
|
model: model,
|
|
266
287
|
citations: citations,
|
|
267
288
|
engine: engine,
|
|
@@ -280,6 +301,16 @@ class DirAskGPTV2 {
|
|
|
280
301
|
json.chunks_only = chunks_only;
|
|
281
302
|
}
|
|
282
303
|
|
|
304
|
+
if (llm === 'ollama') {
|
|
305
|
+
json.gptkey = "";
|
|
306
|
+
json.model = {
|
|
307
|
+
name: action.model,
|
|
308
|
+
url: ollama_integration.value.url,
|
|
309
|
+
token: ollama_integration.value.token
|
|
310
|
+
}
|
|
311
|
+
json.stream = false;
|
|
312
|
+
}
|
|
313
|
+
|
|
283
314
|
|
|
284
315
|
if (ns.hybrid === true) {
|
|
285
316
|
json.search_type = 'hybrid';
|
|
@@ -301,13 +332,12 @@ class DirAskGPTV2 {
|
|
|
301
332
|
json.chat_history_dict = await this.transcriptToLLM(transcript);
|
|
302
333
|
}
|
|
303
334
|
|
|
304
|
-
if (
|
|
335
|
+
if (reranking === true) {
|
|
305
336
|
json.reranking = true;
|
|
306
337
|
json.reranking_multiplier = 3;
|
|
307
338
|
json.reranker_model = "cross-encoder/ms-marco-MiniLM-L-6-v2";
|
|
308
339
|
}
|
|
309
340
|
|
|
310
|
-
|
|
311
341
|
winston.debug("DirAskGPTV2 json:", json);
|
|
312
342
|
|
|
313
343
|
let kb_endpoint = process.env.KB_ENDPOINT_QA;
|
|
@@ -331,7 +361,8 @@ class DirAskGPTV2 {
|
|
|
331
361
|
HTTPREQUEST, async (err, resbody) => {
|
|
332
362
|
|
|
333
363
|
if (err) {
|
|
334
|
-
winston.error("DirAskGPTV2 error: ", err?.
|
|
364
|
+
winston.error("DirAskGPTV2 error: ", err?.response);
|
|
365
|
+
this.logger.error(`[Ask Knowledge Base] Error getting answer`);
|
|
335
366
|
await this.#assignAttributes(action, answer, source);
|
|
336
367
|
if (callback) {
|
|
337
368
|
if (falseIntent) {
|
|
@@ -357,7 +388,7 @@ class DirAskGPTV2 {
|
|
|
357
388
|
|
|
358
389
|
} else {
|
|
359
390
|
await this.#assignAttributes(action, resbody.answer, resbody.source, resbody.content_chunks);
|
|
360
|
-
if (publicKey === true) {
|
|
391
|
+
if (publicKey === true && !chunks_only) {
|
|
361
392
|
let tokens_usage = {
|
|
362
393
|
tokens: resbody.prompt_token_size,
|
|
363
394
|
model: json.model
|
|
@@ -377,10 +408,12 @@ class DirAskGPTV2 {
|
|
|
377
408
|
}
|
|
378
409
|
} else {
|
|
379
410
|
await this.#assignAttributes(action, answer, source);
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
411
|
+
if (!skip_unanswered) {
|
|
412
|
+
kbService.addUnansweredQuestion(this.projectId, json.namespace, json.question, this.token).catch((err) => {
|
|
413
|
+
winston.error("DirAskGPTV2 - Error adding unanswered question: ", err);
|
|
414
|
+
this.logger.warn("[Ask Knowledge Base] Unable to add unanswered question", json.question, "to namespacae", json.namespace);
|
|
415
|
+
})
|
|
416
|
+
}
|
|
384
417
|
if (falseIntent) {
|
|
385
418
|
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
386
419
|
callback(true);
|
|
@@ -451,6 +484,18 @@ class DirAskGPTV2 {
|
|
|
451
484
|
}
|
|
452
485
|
}
|
|
453
486
|
|
|
487
|
+
async checkMandatoryParameters(action) {
|
|
488
|
+
return new Promise((resolve, reject) => {
|
|
489
|
+
let params = ['question', 'llm', 'model']; // mandatory params
|
|
490
|
+
params.forEach((p) => {
|
|
491
|
+
if (!action[p]) {
|
|
492
|
+
reject(p)
|
|
493
|
+
}
|
|
494
|
+
})
|
|
495
|
+
resolve(true);
|
|
496
|
+
})
|
|
497
|
+
}
|
|
498
|
+
|
|
454
499
|
/**
|
|
455
500
|
* Transforms the transcirpt array in a dictionary like '0': { "question": "xxx", "answer":"xxx"}
|
|
456
501
|
* merging consecutive messages with the same role in a single question or answer.
|