@tiledesk/tiledesk-tybot-connector 2.0.46 → 2.0.48
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/logs/app.log +4010 -0
- package/package.json +1 -1
- package/services/KbService.js +24 -4
- package/tiledeskChatbotPlugs/directives/DirAddTags.js +0 -8
- package/tiledeskChatbotPlugs/directives/DirAskGPTV2.js +70 -73
- package/tiledeskChatbotPlugs/directives/DirIteration.js +0 -8
- package/utils/aiUtils.js +43 -0
package/package.json
CHANGED
package/services/KbService.js
CHANGED
|
@@ -73,9 +73,7 @@ class KBService {
|
|
|
73
73
|
})
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
async addUnansweredQuestion(id_project,
|
|
77
|
-
|
|
78
|
-
const json = { namespace, question };
|
|
76
|
+
async addUnansweredQuestion(id_project, data, token) {
|
|
79
77
|
|
|
80
78
|
return new Promise((resolve, reject) => {
|
|
81
79
|
const http_request = {
|
|
@@ -85,7 +83,7 @@ class KBService {
|
|
|
85
83
|
'Authorization': 'JWT ' + token
|
|
86
84
|
},
|
|
87
85
|
method: "POST",
|
|
88
|
-
json:
|
|
86
|
+
json: data
|
|
89
87
|
}
|
|
90
88
|
winston.debug("Kb HttpRequest", http_request);
|
|
91
89
|
|
|
@@ -98,6 +96,28 @@ class KBService {
|
|
|
98
96
|
});
|
|
99
97
|
});
|
|
100
98
|
}
|
|
99
|
+
|
|
100
|
+
async addAnsweredQuestion(id_project, data, token) {
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
const http_request = {
|
|
103
|
+
url: API_ENDPOINT + "/" + id_project + "/kb/answered/",
|
|
104
|
+
headers: {
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
'Authorization': 'JWT ' + token
|
|
107
|
+
},
|
|
108
|
+
json: data,
|
|
109
|
+
method: "POST"
|
|
110
|
+
}
|
|
111
|
+
winston.debug("Kb HttpRequest", http_request);
|
|
112
|
+
httpUtils.request(http_request, (err, response) => {
|
|
113
|
+
if (err) {
|
|
114
|
+
reject(err);
|
|
115
|
+
} else {
|
|
116
|
+
resolve(response);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
const kbService = new KBService();
|
|
@@ -80,19 +80,14 @@ class DirAddTags {
|
|
|
80
80
|
const filled_tags = filler.fill(action.tags, requestVariables);
|
|
81
81
|
winston.debug("(DirAddTags) filled_tags: ", filled_tags);
|
|
82
82
|
|
|
83
|
-
console.log("action.tags: ", action.tags);
|
|
84
|
-
console.log("filled_tags: ", filled_tags);
|
|
85
|
-
|
|
86
83
|
/** use case: CONVERSATION */
|
|
87
84
|
if(target === 'request'){
|
|
88
85
|
|
|
89
86
|
let newTags = filled_tags.split(',').filter(tag => tag !== '').map(el => el.trim())
|
|
90
87
|
this.logger.native("[Add Tag] Adding following tags to conversation: ", newTags)
|
|
91
|
-
console.log("newTags: ", newTags);
|
|
92
88
|
|
|
93
89
|
if(action.pushToList){
|
|
94
90
|
newTags.forEach(async (tag) => {
|
|
95
|
-
console.log("add new tag: ", tag);
|
|
96
91
|
let tags = await this.addNewTag(tag)
|
|
97
92
|
if(!tags){
|
|
98
93
|
callback();
|
|
@@ -102,7 +97,6 @@ class DirAddTags {
|
|
|
102
97
|
}
|
|
103
98
|
|
|
104
99
|
winston.debug('(DirAddTags) UPDATE request with newTags', newTags)
|
|
105
|
-
console.log("update request with newTags: ", newTags);
|
|
106
100
|
let updatedRequest = await this.updateRequestWithTags(newTags)
|
|
107
101
|
this.logger.native("[Add Tag] Tags added to conversation")
|
|
108
102
|
if(!updatedRequest){
|
|
@@ -202,9 +196,7 @@ class DirAddTags {
|
|
|
202
196
|
return new Promise((resolve) => {
|
|
203
197
|
let json = []
|
|
204
198
|
let filteredTags = tags.map((tag) => ({tag: tag, color: '#f0806f'}))
|
|
205
|
-
console.log("tags: ", tags);
|
|
206
199
|
json.push(...filteredTags)
|
|
207
|
-
console.log("json: ", json);
|
|
208
200
|
winston.debug('(httprequest) DirAddTags updateRequestWithTags tags: ', json)
|
|
209
201
|
const HTTPREQUEST = {
|
|
210
202
|
url: this.API_ENDPOINT + "/" + this.context.projectId + "/requests/" + this.requestId + '/tag',
|
|
@@ -19,6 +19,7 @@ const default_engine = require('../../config/kb/engine');
|
|
|
19
19
|
const default_engine_hybrid = require('../../config/kb/engine.hybrid');
|
|
20
20
|
const default_embedding = require("../../config/kb/embedding");
|
|
21
21
|
const PromptManager = require('../../config/kb/prompt/rag/PromptManager');
|
|
22
|
+
const { MODELS_MULTIPLIER } = require("../../utils/aiUtils");
|
|
22
23
|
|
|
23
24
|
//const ragPromptManager = new PromptManager(path.join(__dirname, '../../config/kb/prompt/rag'));
|
|
24
25
|
const ragPromptManager = new PromptManager(path.join(__dirname, '../../config/kb/prompt/rag'));
|
|
@@ -95,44 +96,26 @@ class DirAskGPTV2 {
|
|
|
95
96
|
callback();
|
|
96
97
|
return;
|
|
97
98
|
}
|
|
98
|
-
|
|
99
|
+
|
|
99
100
|
let trueIntent = action.trueIntent;
|
|
100
101
|
let falseIntent = action.falseIntent;
|
|
101
102
|
let trueIntentAttributes = action.trueIntentAttributes;
|
|
102
103
|
let falseIntentAttributes = action.falseIntentAttributes;
|
|
103
|
-
|
|
104
|
+
|
|
104
105
|
winston.debug("DirAskGPTV2 trueIntent", trueIntent)
|
|
105
106
|
winston.debug("DirAskGPTV2 falseIntent", falseIntent)
|
|
106
107
|
winston.debug("DirAskGPTV2 trueIntentAttributes", trueIntentAttributes)
|
|
107
108
|
winston.debug("DirAskGPTV2 falseIntentAttributes", falseIntentAttributes)
|
|
108
|
-
|
|
109
|
+
|
|
109
110
|
// default values
|
|
110
111
|
let answer = "No answers";
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
let temperature = 0.7;
|
|
115
|
-
let max_tokens = 256;
|
|
116
|
-
let top_k = 4;
|
|
117
|
-
let alpha;
|
|
118
|
-
let transcript;
|
|
119
|
-
let citations = false;
|
|
120
|
-
let chunks_only = false;
|
|
121
|
-
let engine;
|
|
122
|
-
let embedding;
|
|
123
|
-
let reranking;
|
|
124
|
-
let reranking_multiplier;
|
|
125
|
-
let skip_unanswered = false;
|
|
126
|
-
let source = null;
|
|
127
|
-
|
|
128
|
-
if (!action.llm) {
|
|
129
|
-
action.llm = "openai";
|
|
130
|
-
}
|
|
131
|
-
|
|
112
|
+
action.llm ??= "openai";
|
|
113
|
+
action.model ??= "gpt-4o";
|
|
114
|
+
|
|
132
115
|
await this.checkMandatoryParameters(action).catch( async (missing_param) => {
|
|
133
116
|
this.logger.error(`[Ask Knowledge Base] missing attribute '${missing_param}'`);
|
|
134
117
|
await this.chatbot.addParameter("flowError", `AskKnowledgeBase Error: '${missing_param}' attribute is undefined`);
|
|
135
|
-
await this.#assignAttributes(action, answer
|
|
118
|
+
await this.#assignAttributes(action, answer);
|
|
136
119
|
if (falseIntent) {
|
|
137
120
|
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
138
121
|
callback(true);
|
|
@@ -142,52 +125,35 @@ class DirAskGPTV2 {
|
|
|
142
125
|
return Promise.reject();
|
|
143
126
|
})
|
|
144
127
|
|
|
145
|
-
|
|
146
|
-
namespace =
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
max_tokens = action.max_tokens;
|
|
162
|
-
}
|
|
163
|
-
if (action.alpha) {
|
|
164
|
-
alpha = action.alpha;
|
|
165
|
-
}
|
|
166
|
-
if (action.citations) {
|
|
167
|
-
citations = action.citations;
|
|
168
|
-
}
|
|
169
|
-
if (action.chunks_only) {
|
|
170
|
-
chunks_only = action.chunks_only;
|
|
171
|
-
}
|
|
172
|
-
if (action.reranking) {
|
|
173
|
-
reranking = action.reranking;
|
|
174
|
-
}
|
|
175
|
-
if (action.reranking_multiplier) {
|
|
176
|
-
reranking_multiplier = action.reranking_multiplier;
|
|
177
|
-
}
|
|
178
|
-
if (action.skip_unanswered) {
|
|
179
|
-
skip_unanswered = action.skip_unanswered;
|
|
180
|
-
}
|
|
128
|
+
let {
|
|
129
|
+
namespace = this.context.projectId,
|
|
130
|
+
llm,
|
|
131
|
+
model,
|
|
132
|
+
temperature = 0.7,
|
|
133
|
+
max_tokens = 2048,
|
|
134
|
+
top_k = 4,
|
|
135
|
+
alpha = 0.5,
|
|
136
|
+
citations = false,
|
|
137
|
+
chunks_only = false,
|
|
138
|
+
reranking = false,
|
|
139
|
+
reranking_multiplier = 3,
|
|
140
|
+
skip_unanswered = false,
|
|
141
|
+
use_hyde = false,
|
|
142
|
+
use_cache = false,
|
|
143
|
+
} = action;
|
|
181
144
|
|
|
145
|
+
let transcript;
|
|
146
|
+
|
|
182
147
|
let requestVariables = null;
|
|
183
148
|
requestVariables =
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
149
|
+
await TiledeskChatbot.allParametersStatic(
|
|
150
|
+
this.tdcache, this.requestId
|
|
151
|
+
);
|
|
152
|
+
|
|
188
153
|
const filler = new Filler();
|
|
189
154
|
const filled_question = filler.fill(action.question, requestVariables);
|
|
190
155
|
const filled_context = filler.fill(action.context, requestVariables)
|
|
156
|
+
|
|
191
157
|
|
|
192
158
|
if (action.history) {
|
|
193
159
|
this.logger.native("[Ask Knowledge Base] use chat transcript")
|
|
@@ -206,9 +172,10 @@ class DirAskGPTV2 {
|
|
|
206
172
|
winston.verbose("DirAskGPT transcript_string is undefined. Skip JSON translation for chat history")
|
|
207
173
|
}
|
|
208
174
|
}
|
|
209
|
-
|
|
210
|
-
let key;
|
|
175
|
+
|
|
211
176
|
let publicKey = false;
|
|
177
|
+
let embedding;
|
|
178
|
+
let engine;
|
|
212
179
|
|
|
213
180
|
try {
|
|
214
181
|
model = await aiController.resolveLLMConfig(this.projectId, llm, model, this.token);
|
|
@@ -280,7 +247,7 @@ class DirAskGPTV2 {
|
|
|
280
247
|
}
|
|
281
248
|
|
|
282
249
|
let ns;
|
|
283
|
-
|
|
250
|
+
|
|
284
251
|
if (action.namespaceAsName) {
|
|
285
252
|
// Namespace could be an attribute
|
|
286
253
|
const filled_namespace = filler.fill(action.namespace, requestVariables)
|
|
@@ -305,7 +272,7 @@ class DirAskGPTV2 {
|
|
|
305
272
|
callback();
|
|
306
273
|
return;
|
|
307
274
|
}
|
|
308
|
-
|
|
275
|
+
|
|
309
276
|
if (ns.engine) {
|
|
310
277
|
engine = ns.engine;
|
|
311
278
|
} else {
|
|
@@ -337,7 +304,7 @@ class DirAskGPTV2 {
|
|
|
337
304
|
if (chunks_only) {
|
|
338
305
|
json.chunks_only = chunks_only;
|
|
339
306
|
}
|
|
340
|
-
|
|
307
|
+
|
|
341
308
|
if (ns.hybrid === true) {
|
|
342
309
|
json.search_type = 'hybrid';
|
|
343
310
|
json.alpha = alpha;
|
|
@@ -398,6 +365,14 @@ class DirAskGPTV2 {
|
|
|
398
365
|
json.tags = action.tags;
|
|
399
366
|
}
|
|
400
367
|
|
|
368
|
+
if (use_hyde) {
|
|
369
|
+
json.use_hyde = use_hyde;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (use_cache) {
|
|
373
|
+
json.use_cache = use_cache;
|
|
374
|
+
}
|
|
375
|
+
|
|
401
376
|
winston.debug("DirAskGPTV2 json:", json);
|
|
402
377
|
|
|
403
378
|
let kb_endpoint = process.env.KB_ENDPOINT_QA;
|
|
@@ -426,7 +401,7 @@ class DirAskGPTV2 {
|
|
|
426
401
|
data: err.response?.data,
|
|
427
402
|
});
|
|
428
403
|
this.logger.error(`[Ask Knowledge Base] Error getting answer`);
|
|
429
|
-
await this.#assignAttributes(action, answer
|
|
404
|
+
await this.#assignAttributes(action, answer);
|
|
430
405
|
if (callback) {
|
|
431
406
|
if (falseIntent) {
|
|
432
407
|
await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
@@ -451,15 +426,31 @@ class DirAskGPTV2 {
|
|
|
451
426
|
|
|
452
427
|
} else {
|
|
453
428
|
await this.#assignAttributes(action, resbody.answer, resbody.source, resbody.content_chunks);
|
|
429
|
+
let tokens = resbody.prompt_token_size;
|
|
454
430
|
if (publicKey === true && !chunks_only) {
|
|
431
|
+
|
|
455
432
|
let tokens_usage = {
|
|
456
433
|
tokens: resbody.prompt_token_size,
|
|
457
434
|
model: json.model
|
|
458
435
|
}
|
|
436
|
+
|
|
437
|
+
let multiplier = MODELS_MULTIPLIER[json.model.name] ?? 1;
|
|
438
|
+
tokens = tokens * multiplier;
|
|
459
439
|
quotasService.updateQuote(this.projectId, this.token, tokens_usage).catch((err) => {
|
|
460
440
|
winston.error("Error updating quota: ", err);
|
|
461
441
|
})
|
|
462
442
|
}
|
|
443
|
+
|
|
444
|
+
const data = {
|
|
445
|
+
namespace: json.namespace,
|
|
446
|
+
question: json.question,
|
|
447
|
+
answer: resbody.answer,
|
|
448
|
+
request_id: this.requestId,
|
|
449
|
+
tokens: tokens
|
|
450
|
+
}
|
|
451
|
+
kbService.addAnsweredQuestion(this.projectId, data, this.token).catch((err) => {
|
|
452
|
+
winston.error("Error adding answered question: ", err);
|
|
453
|
+
})
|
|
463
454
|
|
|
464
455
|
if (trueIntent) {
|
|
465
456
|
await this.#executeCondition(true, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
|
|
@@ -471,9 +462,15 @@ class DirAskGPTV2 {
|
|
|
471
462
|
}
|
|
472
463
|
} else {
|
|
473
464
|
winston.info("DirAskGPTV2 resbody else case: ", resbody);
|
|
474
|
-
await this.#assignAttributes(action, answer
|
|
465
|
+
await this.#assignAttributes(action, answer);
|
|
475
466
|
if (!skip_unanswered) {
|
|
476
|
-
|
|
467
|
+
const data = {
|
|
468
|
+
namespace: json.namespace,
|
|
469
|
+
question: json.question,
|
|
470
|
+
request_id: this.requestId
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
kbService.addUnansweredQuestion(this.projectId, data, this.token).catch((err) => {
|
|
477
474
|
winston.error("DirAskGPTV2 - Error adding unanswered question: ", {
|
|
478
475
|
status: err.response?.status,
|
|
479
476
|
statusText: err.response?.statusText,
|
|
@@ -22,7 +22,6 @@ class DirIteration {
|
|
|
22
22
|
|
|
23
23
|
execute(directive, callback) {
|
|
24
24
|
winston.verbose("Execute Iteration directive");
|
|
25
|
-
console.log("directive: ", directive);
|
|
26
25
|
let action;
|
|
27
26
|
if (directive.action) {
|
|
28
27
|
action = directive.action;
|
|
@@ -83,7 +82,6 @@ class DirIteration {
|
|
|
83
82
|
*/
|
|
84
83
|
async #initializeIteration(action, actionId, callback) {
|
|
85
84
|
winston.debug("[Iteration] Initializing iteration state");
|
|
86
|
-
console.log("[Iteration] Initializing iteration state");
|
|
87
85
|
|
|
88
86
|
const iterable = action.iterable;
|
|
89
87
|
const goToIntent = action.goToIntent;
|
|
@@ -96,7 +94,6 @@ class DirIteration {
|
|
|
96
94
|
|
|
97
95
|
if (!iterableValue) {
|
|
98
96
|
winston.verbose("[Iteration] Iterable object is undefined");
|
|
99
|
-
console.log("[Iteration] Iterable object is undefined");
|
|
100
97
|
this.logger.warn("[Iteration] Iterable object is undefined");
|
|
101
98
|
callback(true);
|
|
102
99
|
return;
|
|
@@ -107,7 +104,6 @@ class DirIteration {
|
|
|
107
104
|
|
|
108
105
|
if (!iterableArray) {
|
|
109
106
|
winston.verbose("[Iteration] Could not convert iterable to array");
|
|
110
|
-
console.log("[Iteration] Could not convert iterable to array");
|
|
111
107
|
this.logger.error(`[Iteration] Could not convert iterable '${iterable}' to array | type: ${typeof iterableValue}`);
|
|
112
108
|
callback(true);
|
|
113
109
|
return;
|
|
@@ -115,7 +111,6 @@ class DirIteration {
|
|
|
115
111
|
|
|
116
112
|
if (iterableArray.length === 0) {
|
|
117
113
|
winston.verbose("[Iteration] Iterable array is empty. Exit...")
|
|
118
|
-
console.log("[Iteration] Iterable array is empty. Exit...")
|
|
119
114
|
this.logger.warn("[Iteration] Iterable array is empty. Exit...")
|
|
120
115
|
callback(true);
|
|
121
116
|
return;
|
|
@@ -133,7 +128,6 @@ class DirIteration {
|
|
|
133
128
|
|
|
134
129
|
await this.#saveIterationState(actionId, iterationState);
|
|
135
130
|
this.logger.native(`[Iteration] Initialized iteration with ${iterableArray.length} items`);
|
|
136
|
-
console.log(`[Iteration] Initialized iteration with ${iterableArray.length} items`);
|
|
137
131
|
|
|
138
132
|
// Process first item
|
|
139
133
|
await this.#processCurrentItem(iterationState, actionId, goToIntent, output, callback);
|
|
@@ -141,7 +135,6 @@ class DirIteration {
|
|
|
141
135
|
|
|
142
136
|
async #continueIteration(iterationState, actionId, callback) {
|
|
143
137
|
winston.debug(`[Iteration] Continuing iteration from index ${iterationState.currentIndex}`);
|
|
144
|
-
console.log(`[Iteration] Continuing iteration from index ${iterationState.currentIndex}`);
|
|
145
138
|
|
|
146
139
|
// Increment index
|
|
147
140
|
iterationState.currentIndex += 1;
|
|
@@ -150,7 +143,6 @@ class DirIteration {
|
|
|
150
143
|
if (iterationState.currentIndex >= iterationState.totalItems) {
|
|
151
144
|
this.logger.native("[Iteration] Iteration completed");
|
|
152
145
|
await this.#clearIterationState(actionId);
|
|
153
|
-
console.log("[Iteration] Iteration completed");
|
|
154
146
|
callback(false);
|
|
155
147
|
return;
|
|
156
148
|
}
|
package/utils/aiUtils.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const winston = require('./winston');
|
|
2
|
+
|
|
3
|
+
// MODELS_MULTIPLIER = {
|
|
4
|
+
// "gpt-3.5-turbo": 0.6,
|
|
5
|
+
// "gpt-4": 25,
|
|
6
|
+
// "gpt-4-turbo-preview": 12
|
|
7
|
+
// }
|
|
8
|
+
|
|
9
|
+
loadMultiplier();
|
|
10
|
+
function loadMultiplier() {
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
let models_string = process.env.AI_MODELS;
|
|
14
|
+
winston.debug("(loadMultiplier) models_string: ", models_string)
|
|
15
|
+
let models = {};
|
|
16
|
+
|
|
17
|
+
if (!models_string) {
|
|
18
|
+
winston.info("AI_MODELS not defined");
|
|
19
|
+
winston.info("AI Models: ", models)
|
|
20
|
+
return models;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let models_string_trimmed = models_string.replace(/ /g,'');
|
|
24
|
+
winston.debug("(loadMultiplier) models_string_trimmed: ", models_string_trimmed)
|
|
25
|
+
|
|
26
|
+
let splitted_string = models_string_trimmed.split(";");
|
|
27
|
+
winston.debug("splitted_string: ", splitted_string)
|
|
28
|
+
|
|
29
|
+
splitted_string.forEach(m => {
|
|
30
|
+
m_split = m.split(":");
|
|
31
|
+
if (!m_split[1]) {
|
|
32
|
+
multiplier = null;
|
|
33
|
+
} else {
|
|
34
|
+
multiplier = Number(m_split[1]);;
|
|
35
|
+
}
|
|
36
|
+
models[m_split[0]] = multiplier;
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
winston.info("AI Models: ", models)
|
|
40
|
+
return models;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = { MODELS_MULTIPLIER: loadMultiplier() }
|