@tiledesk/tiledesk-server 2.9.32 → 2.9.33

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
+ # 2.10.0
9
+ - Added support for engine to namespace
10
+ - Added support for advanced context to kb
11
+ - Added support for scrape types to kb
12
+ - Updated tybot-connector to 0.2.112
13
+ - Updated vxml-connector to 0.1.54
14
+ - Updated widget.json translation file
15
+
8
16
  # 2.9.32
9
17
  - Added voice filters in get requests
10
18
  - Added endpoint to get all projects
@@ -61,6 +61,7 @@
61
61
  "CLOSE_CHAT": "Close chat",
62
62
  "MINIMIZE":"Minimize",
63
63
  "MAXIMIZE":"Maximize",
64
+ "CONFIRM_CLOSE_CHAT":"Are you sure you wanna close this chat?",
64
65
 
65
66
  "INFO_SUPPORT_USER_ADDED_SUBJECT":"you",
66
67
  "INFO_SUPPORT_USER_ADDED_YOU_VERB":"you have been added ",
@@ -160,6 +161,7 @@
160
161
  "CLOSE_CHAT": "Chiudi chat",
161
162
  "MINIMIZE":"Minimizza",
162
163
  "MAXIMIZE":"Massimizza",
164
+ "CONFIRM_CLOSE_CHAT":"Vuoi davvero chiudere questa chat?",
163
165
 
164
166
  "INFO_SUPPORT_USER_ADDED_SUBJECT":"tu",
165
167
  "INFO_SUPPORT_USER_ADDED_YOU_VERB":"sei stato aggiunto ",
@@ -259,6 +261,7 @@
259
261
  "CLOSE_CHAT": "Fermer le chat",
260
262
  "MINIMIZE":"Minimiser",
261
263
  "MAXIMIZE":"Maximiser",
264
+ "CONFIRM_CLOSE_CHAT":"Etes-vous sûr de vouloir fermer cette discussion?",
262
265
 
263
266
  "INFO_SUPPORT_USER_ADDED_SUBJECT":"toi",
264
267
  "INFO_SUPPORT_USER_ADDED_YOU_VERB":"ont été ajoutés à ",
@@ -358,6 +361,7 @@
358
361
  "CLOSE_CHAT": "Cerrar chat",
359
362
  "MINIMIZE":"Minimizar",
360
363
  "MAXIMIZE":"Maximizar",
364
+ "CONFIRM_CLOSE_CHAT":"¿Estás segura de que quieres cerrar este chat?",
361
365
 
362
366
  "INFO_SUPPORT_USER_ADDED_SUBJECT":"tú",
363
367
  "INFO_SUPPORT_USER_ADDED_YOU_VERB":"han sido agregados a ",
@@ -457,6 +461,7 @@
457
461
  "CLOSE_CHAT": "Chat schließen",
458
462
  "MINIMIZE":"Minimieren",
459
463
  "MAXIMIZE":"Maximieren",
464
+ "CONFIRM_CLOSE_CHAT":"Möchten Sie diesen Chat wirklich schließen?",
460
465
 
461
466
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "Sie",
462
467
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "Sie wurden hinzugefügt ",
@@ -556,6 +561,7 @@
556
561
  "CLOSE_CHAT": "Fechar bate-papo",
557
562
  "MINIMIZE":"Minimizar",
558
563
  "MAXIMIZE":"Maximizar",
564
+ "CONFIRM_CLOSE_CHAT":"Tem certeza de que deseja fechar este bate-papo?",
559
565
 
560
566
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "você",
561
567
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "você foi adicionado ",
@@ -655,6 +661,7 @@
655
661
  "CLOSE_CHAT": "Закрыть чат",
656
662
  "MINIMIZE":"Свести к минимуму",
657
663
  "MAXIMIZE":"Максимизировать",
664
+ "CONFIRM_CLOSE_CHAT":"Вы уверены, что хотите закрыть этот чат?",
658
665
 
659
666
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "вы",
660
667
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "вы добавлены ",
@@ -754,6 +761,7 @@
754
761
  "CLOSE_CHAT": "Sohbeti kapat",
755
762
  "MINIMIZE":"Küçült",
756
763
  "MAXIMIZE":"Büyüt",
764
+ "CONFIRM_CLOSE_CHAT":"Bu sohbeti kapatmak istediğinizden emin misiniz?",
757
765
 
758
766
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "siz",
759
767
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "eklendiniz ",
@@ -855,6 +863,7 @@
855
863
  "CLOSE_CHAT": "Затвори ћаскање",
856
864
  "MINIMIZE":"Минимизирајте",
857
865
  "MAXIMIZE":"Максимизирајте",
866
+ "CONFIRM_CLOSE_CHAT":"Да ли сте сигурни да желите да затворите ово ћаскање?",
858
867
 
859
868
  "INFO_SUPPORT_USER_ADDED_SUBJECT":"ти",
860
869
  "INFO_SUPPORT_USER_ADDED_YOU_VERB":"додани сте",
@@ -956,6 +965,7 @@
956
965
  "CLOSE_CHAT": "إغلاق الدردشة",
957
966
  "MINIMIZE":"تصغير",
958
967
  "MAXIMIZE":"تحقيق أقصى قدر",
968
+ "CONFIRM_CLOSE_CHAT":"هل أنت متأكد أنك تريد إغلاق هذه الدردشة؟",
959
969
 
960
970
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "أنت",
961
971
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "لقد تم اضافتك ",
@@ -1057,6 +1067,7 @@
1057
1067
  "CLOSE_CHAT": "Закрити чат",
1058
1068
  "MINIMIZE":"Згорнути",
1059
1069
  "MAXIMIZE":"Максимізувати",
1070
+ "CONFIRM_CLOSE_CHAT":"Ви впевнені, що бажаєте закрити цей чат?",
1060
1071
 
1061
1072
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "ти",
1062
1073
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "вас додали ",
@@ -1157,6 +1168,7 @@
1157
1168
  "CLOSE_CHAT":"Stäng chatten",
1158
1169
  "MINIMIZE":"Minimera",
1159
1170
  "MAXIMIZE":"Maximera",
1171
+ "CONFIRM_CLOSE_CHAT":"Är du säker på att du vill stänga den här chatten?",
1160
1172
 
1161
1173
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "du",
1162
1174
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "du har lagts till ",
@@ -1257,6 +1269,7 @@
1257
1269
  "CLOSE_CHAT":"Чатты жабу",
1258
1270
  "MINIMIZE":"Кішірейту",
1259
1271
  "MAXIMIZE":"Үлкейту",
1272
+ "CONFIRM_CLOSE_CHAT":"Бұл чатты шынымен жапқыңыз келе ме?",
1260
1273
 
1261
1274
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "сен",
1262
1275
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "сіз қосылдыңыз ",
@@ -1357,6 +1370,7 @@
1357
1370
  "CLOSE_CHAT":"Chatni yopish",
1358
1371
  "MINIMIZE":"Minimallashtirish",
1359
1372
  "MAXIMIZE":"Maksimallashtirish",
1373
+ "CONFIRM_CLOSE_CHAT":"Bu chatni yopmoqchi ekanligingizga ishonchingiz komilmi?",
1360
1374
 
1361
1375
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "siz",
1362
1376
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "qo'shildingiz ",
@@ -1457,6 +1471,7 @@
1457
1471
  "CLOSE_CHAT": "Söhbəti bağlayın",
1458
1472
  "MINIMIZE":"Minimallaşdırın",
1459
1473
  "MAXIMIZE":"Maksimallaşdırın",
1474
+ "CONFIRM_CLOSE_CHAT":"Bu söhbəti bağlamaq istədiyinizə əminsiniz?",
1460
1475
 
1461
1476
  "INFO_SUPPORT_USER_ADDED_SUBJECT": "Sən",
1462
1477
  "INFO_SUPPORT_USER_ADDED_YOU_VERB": "siz əlavə olundunuz ",
package/deploy.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  git pull
2
- npm version patch
2
+ npm version minor
3
3
  version=`node -e 'console.log(require("./package.json").version)'`
4
4
  echo "version $version"
5
5
 
@@ -2,6 +2,31 @@ var mongoose = require('mongoose');
2
2
  var Schema = mongoose.Schema;
3
3
  var winston = require('../config/winston');
4
4
 
5
+ var EngineSchema = new Schema({
6
+ name: {
7
+ type: String,
8
+ required: true
9
+ },
10
+ type: {
11
+ type: String,
12
+ required: true
13
+ },
14
+ apikey: {
15
+ type: String,
16
+ required: false
17
+ },
18
+ vector_size: {
19
+ type: Number,
20
+ required: true
21
+ },
22
+ index_name: {
23
+ type: String,
24
+ required: true
25
+ }
26
+ }, {
27
+ _id: false // This is schema is always used as an embedded object inside NamespaceSchema
28
+ })
29
+
5
30
  var NamespaceSchema = new Schema({
6
31
  id_project: {
7
32
  type: String,
@@ -22,6 +47,10 @@ var NamespaceSchema = new Schema({
22
47
  default: {
23
48
  type: Boolean,
24
49
  default: false
50
+ },
51
+ engine: {
52
+ type: EngineSchema,
53
+ required: false
25
54
  }
26
55
  }, {
27
56
  timestamps: true
@@ -59,12 +88,34 @@ var KBSchema = new Schema({
59
88
  status: {
60
89
  type: Number,
61
90
  required: false
91
+ },
92
+ scrape_type: {
93
+ type: Number,
94
+ required: false
95
+ },
96
+ scrape_options: {
97
+ type: Object,
98
+ required: false,
99
+ default: undefined,
100
+ tags_to_extract: {
101
+ type: Array,
102
+ required: false
103
+ },
104
+ unwanted_tags: {
105
+ type: Array,
106
+ required: false
107
+ },
108
+ unwanted_classnames: {
109
+ type: Array,
110
+ required: false
111
+ }
62
112
  }
63
113
  }, {
64
114
  timestamps: true
65
115
  })
66
116
 
67
117
 
118
+
68
119
  // DEPRECATED !! - Start
69
120
  var KBSettingSchema = new Schema({
70
121
  id_project: {
@@ -93,7 +144,7 @@ KBSchema.index({ createdAt: -1, updatedAt: -1 })
93
144
 
94
145
  // DEPRECATED
95
146
  const KBSettings = mongoose.model('KBSettings', KBSettingSchema);
96
-
147
+ const Engine = mongoose.model('Engine', EngineSchema)
97
148
  const Namespace = mongoose.model('Namespace', NamespaceSchema)
98
149
  const KB = mongoose.model('KB', KBSchema)
99
150
 
@@ -105,5 +156,6 @@ const KB = mongoose.model('KB', KBSchema)
105
156
  module.exports = {
106
157
  KBSettings: KBSettings,
107
158
  Namespace: Namespace,
159
+ Engine: Engine,
108
160
  KB: KB
109
161
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-server",
3
3
  "description": "The Tiledesk server module",
4
- "version": "2.9.32",
4
+ "version": "2.9.33",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -48,7 +48,7 @@
48
48
  "@tiledesk/tiledesk-rasa-connector": "^1.0.10",
49
49
  "@tiledesk/tiledesk-telegram-connector": "^0.1.14",
50
50
  "@tiledesk/tiledesk-train-jobworker": "^0.0.11",
51
- "@tiledesk/tiledesk-tybot-connector": "^0.2.107",
51
+ "@tiledesk/tiledesk-tybot-connector": "^0.2.112",
52
52
  "@tiledesk/tiledesk-whatsapp-connector": "^0.1.73",
53
53
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.8",
54
54
  "@tiledesk/tiledesk-sms-connector": "^0.1.10",
package/routes/kb.js CHANGED
@@ -1,6 +1,7 @@
1
1
  var express = require('express');
2
- var { Namespace } = require('../models/kb_setting');
3
- var { KB } = require('../models/kb_setting');
2
+ var { Namespace, KB, Engine } = require('../models/kb_setting');
3
+ // var { KB } = require('../models/kb_setting');
4
+ // var { Engine } = require('../models/kb_setting')
4
5
  var router = express.Router();
5
6
  var winston = require('../config/winston');
6
7
  var multer = require('multer')
@@ -17,6 +18,7 @@ let Integration = require('../models/integrations');
17
18
  var parsecsv = require("fast-csv");
18
19
 
19
20
  const { MODELS_MULTIPLIER } = require('../utils/aiUtils');
21
+ const { body } = require('express-validator');
20
22
 
21
23
  const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL;
22
24
  const JOB_TOPIC_EXCHANGE = process.env.JOB_TOPIC_EXCHANGE_TRAIN || 'tiledesk-trainer';
@@ -45,6 +47,13 @@ let default_preview_settings = {
45
47
  //context: "You are an awesome AI Assistant."
46
48
  context: null
47
49
  }
50
+ let default_engine = {
51
+ name: "pinecone",
52
+ type: "pod",
53
+ apikey: "",
54
+ vector_size: 1536,
55
+ index_name: process.env.PINECONE_INDEX
56
+ }
48
57
 
49
58
  //let default_context = "Answer if and ONLY if the answer is contained in the context provided. If the answer is not contained in the context provided ALWAYS answer with <NOANS>\n{context}"
50
59
  //let default_context = "You are an helpful assistant for question-answering tasks.\nUse ONLY the following pieces of retrieved context to answer the question.\nIf you don't know the answer, just say that you don't know.\nIf none of the retrieved context answer the question, add this word to the end <NOANS>\n\n{context}";
@@ -68,9 +77,9 @@ router.post('/scrape/single', async (req, res) => {
68
77
  let data = req.body;
69
78
  winston.debug("/scrape/single data: ", data);
70
79
 
71
- if (!data.scrape_type) {
72
- data.scrape_type = 1;
73
- }
80
+ // if (!data.scrape_type) {
81
+ // data.scrape_type = 1;
82
+ // }
74
83
 
75
84
  let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
76
85
  winston.error("find namespaces error: ", err)
@@ -112,11 +121,28 @@ router.post('/scrape/single', async (req, res) => {
112
121
  json.content = kb.content;
113
122
  }
114
123
 
115
- json.scrape_type = 1;
116
- if (data.scrape_type) {
117
- json.scrape_type = data.scrape_type;
124
+ // json.scrape_type = 1;
125
+ // if (data.scrape_type) {
126
+ // json.scrape_type = data.scrape_type;
127
+ // }
128
+
129
+ if (kb.scrape_type) {
130
+ json.scrape_type = kb.scrape_type
118
131
  }
119
132
 
133
+ if (kb.scrape_options) {
134
+ json.parameters_scrape_type_4 = {
135
+ tags_to_extract: kb.scrape_options.tags_to_extract,
136
+ unwanted_tags: kb.scrape_options.unwanted_tags,
137
+ unwanted_classnames: kb.scrape_options.unwanted_classnames
138
+ }
139
+ }
140
+
141
+ let ns = namespaces.find(n => n.id === kb.namespace);
142
+ json.engine = ns.engine || default_engine;
143
+
144
+ winston.verbose("/scrape/single json: ", json);
145
+
120
146
  startScrape(json).then((response) => {
121
147
  winston.verbose("startScrape response: ", response);
122
148
  res.status(200).send(response);
@@ -132,6 +158,8 @@ router.post('/scrape/single', async (req, res) => {
132
158
 
133
159
  router.post('/scrape/status', async (req, res) => {
134
160
 
161
+ let project_id = req.projectid;
162
+ // (EXAMPLE) body: { id, namespace }
135
163
  let data = req.body;
136
164
  winston.debug("/scrapeStatus req.body: ", req.body);
137
165
 
@@ -143,6 +171,25 @@ router.post('/scrape/status', async (req, res) => {
143
171
  returnObject = true;
144
172
  }
145
173
 
174
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
175
+ winston.error("find namespaces error: ", err)
176
+ res.status(500).send({ success: false, error: err })
177
+ })
178
+
179
+ if (!namespaces || namespaces.length == 0) {
180
+ let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
181
+ winston.warn(alert);
182
+ res.status(403).send(alert);
183
+ }
184
+
185
+ let namespaceIds = namespaces.map(namespace => namespace.id);
186
+ if (!namespaceIds.includes(data.namespace)) {
187
+ return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
188
+ }
189
+
190
+ let ns = namespaces.find(n => n.id === data.namespace);
191
+ data.engine = ns.engine || default_engine;
192
+
146
193
  openaiService.scrapeStatus(data).then(async (response) => {
147
194
 
148
195
  winston.debug("scrapeStatus response.data: ", response.data);
@@ -229,7 +276,7 @@ router.post('/qa', async (req, res) => {
229
276
  }
230
277
 
231
278
  // Check if "Advanced Mode" is active. In such case the default_context must be not appended
232
- if (!data.advanced_context) {
279
+ if (!data.advancedPrompt) {
233
280
  if (data.system_context) {
234
281
  data.system_context = data.system_context + " \n" + contexts[data.model];
235
282
  } else {
@@ -237,9 +284,15 @@ router.post('/qa', async (req, res) => {
237
284
  }
238
285
  }
239
286
 
240
- // if (process.env.NODE_ENV === 'test') {
241
- // return res.status(200).send({ success: true, message: "Question skipped in test environment"});
242
- // }
287
+ let ns = namespaces.find(n => n.id === data.namespace);
288
+ data.engine = ns.engine || default_engine;
289
+
290
+ delete data.advancedPrompt;
291
+ winston.verbose("ask data: ", data);
292
+
293
+ if (process.env.NODE_ENV === 'test') {
294
+ return res.status(200).send({ success: true, message: "Question skipped in test environment"});
295
+ }
243
296
 
244
297
  openaiService.askNamespace(data).then((resp) => {
245
298
  winston.debug("qa resp: ", resp.data);
@@ -317,6 +370,9 @@ router.delete('/delete', async (req, res) => {
317
370
  if (!namespaceIds.includes(data.namespace)) {
318
371
  return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
319
372
  }
373
+
374
+ let ns = namespaces.find(n => n.id === data.namespace);
375
+ data.engine = ns.engine || default_engine;
320
376
 
321
377
  openaiService.deleteIndex(data).then((resp) => {
322
378
  winston.debug("delete resp: ", resp.data);
@@ -352,6 +408,11 @@ router.delete('/deleteall', async (req, res) => {
352
408
  return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
353
409
  }
354
410
 
411
+ let ns = namespaces.find(n => n.id === data.namespace);
412
+ data.engine = ns.engine || default_engine;
413
+
414
+ winston.verbose("/deleteall data: ", data);
415
+
355
416
  openaiService.deleteNamespace(data).then((resp) => {
356
417
  winston.debug("delete namespace resp: ", resp.data);
357
418
  res.status(200).send(resp.data);
@@ -394,7 +455,8 @@ router.get('/namespace/all', async (req, res) => {
394
455
  id: project_id,
395
456
  name: "Default",
396
457
  preview_settings: default_preview_settings,
397
- default: true
458
+ default: true,
459
+ engine: default_engine
398
460
  })
399
461
 
400
462
  new_namespace.save((err, savedNamespace) => {
@@ -448,7 +510,11 @@ router.get('/namespace/:id/chunks/:content_id', async (req, res) => {
448
510
  return res.status(403).send({ success: false, error: "Not allowed. The conten does not belong to the current namespace." })
449
511
  }
450
512
 
451
- openaiService.getContentChunks(namespace_id, content_id).then((resp) => {
513
+ let ns = namespaces.find(n => n.id === namespace_id);
514
+ let engine = ns.engine || default_engine;
515
+ delete engine._id;
516
+
517
+ openaiService.getContentChunks(namespace_id, content_id, engine).then((resp) => {
452
518
  let chunks = resp.data;
453
519
  winston.debug("chunks for content " + content_id);
454
520
  winston.debug("chunks found ", chunks);
@@ -492,7 +558,6 @@ router.get('/namespace/:id/chatbots', async (req, res) => {
492
558
  let chatbots = intents.map(i => i.id_faq_kb);
493
559
  let uniqueChatbots = [...new Set(chatbots)];
494
560
 
495
-
496
561
  let chatbotPromises = uniqueChatbots.map(async (c_id) => {
497
562
  try {
498
563
  let chatbot = await faq_kb.findOne({ _id: c_id, trashed: false });
@@ -527,6 +592,7 @@ router.post('/namespace', async (req, res) => {
527
592
  id: namespace_id,
528
593
  name: body.name,
529
594
  preview_settings: default_preview_settings,
595
+ engine: default_engine
530
596
  })
531
597
 
532
598
  let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
@@ -589,11 +655,23 @@ router.put('/namespace/:id', async (req, res) => {
589
655
 
590
656
  router.delete('/namespace/:id', async (req, res) => {
591
657
 
592
- let id_project = req.projectid;
658
+ let project_id = req.projectid;
593
659
  let namespace_id = req.params.id;
594
660
 
661
+ let namespace = await Namespace.findOne({ id_project: project_id, id: namespace_id }).catch((err) => {
662
+ winston.error("find namespace error: ", err);
663
+ res.status(500).send({ success: false, error: err });
664
+ })
665
+
666
+ if (!namespace) {
667
+ let alert = "No namespace found for id " + namespace_id;
668
+ winston.warn(alert);
669
+ res.status(404).send({ success: false, error: alert })
670
+ }
671
+
595
672
  let data = {
596
- namespace: namespace_id
673
+ namespace: namespace_id,
674
+ engine: namespace.engine || default_engine
597
675
  }
598
676
 
599
677
  if (req.query.contents_only && (req.query.contents_only === true || req.query.contents_only === 'true')) {
@@ -601,7 +679,7 @@ router.delete('/namespace/:id', async (req, res) => {
601
679
  openaiService.deleteNamespace(data).then(async (resp) => {
602
680
  winston.debug("delete namespace resp: ", resp.data);
603
681
 
604
- let deleteResponse = await KB.deleteMany({ id_project: id_project, namespace: namespace_id }).catch((err) => {
682
+ let deleteResponse = await KB.deleteMany({ id_project: project_id, namespace: namespace_id }).catch((err) => {
605
683
  winston.error("deleteMany error: ", err);
606
684
  return res.status(500).send({ success: false, error: err });
607
685
  })
@@ -635,7 +713,7 @@ router.delete('/namespace/:id', async (req, res) => {
635
713
  openaiService.deleteNamespace(data).then(async (resp) => {
636
714
  winston.debug("delete namespace resp: ", resp.data);
637
715
 
638
- let deleteResponse = await KB.deleteMany({ id_project: id_project, namespace: namespace_id }).catch((err) => {
716
+ let deleteResponse = await KB.deleteMany({ id_project: project_id, namespace: namespace_id }).catch((err) => {
639
717
  winston.error("deleteMany error: ", err);
640
718
  return res.status(500).send({ success: false, error: err });
641
719
  })
@@ -831,7 +909,7 @@ router.post('/', async (req, res) => {
831
909
  if (!namespaceIds.includes(body.namespace)) {
832
910
  return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
833
911
  }
834
-
912
+
835
913
  let quoteManager = req.app.get('quote_manager');
836
914
  let limits = await quoteManager.getPlanLimits(req.project);
837
915
  let kbs_limit = limits.kbs;
@@ -848,6 +926,7 @@ router.post('/', async (req, res) => {
848
926
  if (total_count > kbs_limit) {
849
927
  return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
850
928
  }
929
+
851
930
  let new_kb = {
852
931
  id_project: project_id,
853
932
  name: body.name,
@@ -860,6 +939,19 @@ router.post('/', async (req, res) => {
860
939
  if (!new_kb.namespace) {
861
940
  new_kb.namespace = project_id;
862
941
  }
942
+ if (new_kb.type === 'txt') {
943
+ new_kb.scrape_type = 1;
944
+ }
945
+ if (new_kb.type === 'url') {
946
+ if (!body.scrape_type || body.scrape_type === 2) {
947
+ new_kb.scrape_type = 2;
948
+ new_kb.scrape_options = await setDefaultScrapeOptions();
949
+ } else {
950
+ new_kb.scrape_type = body.scrape_type;
951
+ new_kb.scrape_options = body.scrape_options;
952
+ }
953
+ }
954
+
863
955
  winston.debug("adding kb: ", new_kb);
864
956
 
865
957
  KB.findOneAndUpdate({ id_project: project_id, type: 'url', source: new_kb.source }, new_kb, { upsert: true, new: true, rawResult: true }, async (err, raw) => {
@@ -871,26 +963,37 @@ router.post('/', async (req, res) => {
871
963
 
872
964
  res.status(200).send(raw);
873
965
 
966
+ let saved_kb = raw.value;
874
967
  let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
875
968
 
876
969
  let json = {
877
- id: raw.value._id,
878
- type: raw.value.type,
879
- source: raw.value.source,
970
+ id: saved_kb._id,
971
+ type: saved_kb.type,
972
+ source: saved_kb.source,
880
973
  content: "",
881
- namespace: raw.value.namespace,
974
+ namespace: saved_kb.namespace,
882
975
  webhook: webhook
883
976
  }
884
977
  winston.debug("json: ", json);
885
978
 
886
- if (raw.value.content) {
887
- json.content = raw.value.content;
979
+ if (saved_kb.content) {
980
+ json.content = saved_kb.content;
981
+ }
982
+ if (saved_kb.scrape_type) {
983
+ json.scrape_type = saved_kb.scrape_type;
984
+ }
985
+ if (saved_kb.scrape_options) {
986
+ json.parameters_scrape_type_4 = saved_kb.scrape_options;
888
987
  }
988
+ let ns = namespaces.find(n => n.id === body.namespace);
989
+ json.engine = ns.engine || default_engine;
889
990
 
890
991
  let resources = [];
891
992
 
892
993
  resources.push(json);
893
- scheduleScrape(resources);
994
+ if (!process.env.NODE_ENV) {
995
+ scheduleScrape(resources);
996
+ }
894
997
 
895
998
  }
896
999
  })
@@ -908,6 +1011,8 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
908
1011
  }
909
1012
 
910
1013
  let project_id = req.projectid;
1014
+ let scrape_type = req.body.scrape_type;
1015
+ let scrape_options = req.body.scrape_options;
911
1016
 
912
1017
  let namespace_id = req.query.namespace;
913
1018
  if (!namespace_id) {
@@ -956,16 +1061,37 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
956
1061
  let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
957
1062
 
958
1063
  let kbs = [];
959
- list.forEach(url => {
960
- kbs.push({
1064
+ list.forEach( async (url) => {
1065
+ let kb = {
961
1066
  id_project: project_id,
962
1067
  name: url,
963
1068
  source: url,
964
1069
  type: 'url',
965
1070
  content: "",
966
1071
  namespace: namespace_id,
967
- status: -1
968
- })
1072
+ status: -1,
1073
+ scrape_type: scrape_type
1074
+ }
1075
+
1076
+ if (!kb.scrape_type) {
1077
+ scrape_type = 2;
1078
+ }
1079
+
1080
+ if (scrape_type == 2) {
1081
+ kb.scrape_options = {
1082
+ tags_to_extract: ["body"],
1083
+ unwanted_tags: [],
1084
+ unwanted_classnames: []
1085
+ }
1086
+ } else {
1087
+ kb.scrape_options = scrape_options;
1088
+ }
1089
+ // if (scrape_type === 2) {
1090
+ // kb.scrape_options = await setDefaultScrapeOptions();
1091
+ // } else {
1092
+ // kb.scrape_options = await setCustomScrapeOptions(scrape_options);
1093
+ // }
1094
+ kbs.push(kb)
969
1095
  })
970
1096
 
971
1097
  let operations = kbs.map(doc => {
@@ -979,13 +1105,20 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
979
1105
  }
980
1106
  })
981
1107
 
1108
+ console.log("kbs: ", kbs);
1109
+
982
1110
  saveBulk(operations, kbs, project_id).then((result) => {
983
1111
 
1112
+ let ns = namespaces.find(n => n.id === namespace_id);
1113
+ let engine = ns.engine || default_engine;
1114
+
984
1115
  let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
985
- resources = resources.map(({ _id, ...rest }) => {
986
- return { id: _id, webhook: webhook, ...rest };
1116
+ resources = resources.map(({ _id, scrape_options, ...rest }) => {
1117
+ return { id: _id, webhook: webhook, parameters_scrape_type_4: scrape_options, engine: engine, ...rest}
987
1118
  });
1119
+ console.log("resources to be sent to worker: ", resources);
988
1120
  winston.verbose("resources to be sent to worker: ", resources);
1121
+
989
1122
  scheduleScrape(resources);
990
1123
  res.status(200).send(result);
991
1124
 
@@ -1085,9 +1218,13 @@ router.post('/csv', upload.single('uploadFile'), async (req, res) => {
1085
1218
  })
1086
1219
 
1087
1220
  saveBulk(operations, kbs, project_id).then((result) => {
1221
+
1222
+ let ns = namespaces.find(n => n.id === namespace_id);
1223
+ let engine = ns.engine || default_engine;
1224
+
1088
1225
  let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
1089
1226
  resources = resources.map(({ _id, ...rest}) => {
1090
- return { id: _id, webhooh: webhook, ...rest };
1227
+ return { id: _id, webhooh: webhook, engine: engine, ...rest };
1091
1228
  })
1092
1229
  winston.verbose("resources to be sent to worker: ", resources);
1093
1230
  if (!process.env.NODE_ENV) {
@@ -1166,7 +1303,6 @@ router.delete('/:kb_id', async (req, res) => {
1166
1303
  let kb_id = req.params.kb_id;
1167
1304
  winston.verbose("delete kb_id " + kb_id);
1168
1305
 
1169
-
1170
1306
  let kb = await KB.findOne({ id_project: project_id, _id: kb_id}).catch((err) => {
1171
1307
  winston.warn("Unable to find kb. Error: ", err);
1172
1308
  return res.status(500).send({ success: false, error: err })
@@ -1186,6 +1322,16 @@ router.delete('/:kb_id', async (req, res) => {
1186
1322
  data.namespace = project_id;
1187
1323
  }
1188
1324
 
1325
+ let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
1326
+ winston.error("find namespaces error: ", err)
1327
+ res.status(500).send({ success: false, error: err })
1328
+ })
1329
+
1330
+ let ns = namespaces.find(n => n.id === data.namespace);
1331
+ data.engine = ns.engine || default_engine;
1332
+
1333
+ winston.verbose("/:delete_id data: ", data);
1334
+
1189
1335
  openaiService.deleteIndex(data).then((resp) => {
1190
1336
  winston.debug("delete resp: ", resp.data);
1191
1337
  if (resp.data.success === true) {
@@ -1369,6 +1515,30 @@ async function getKeyFromIntegrations(project_id) {
1369
1515
  }
1370
1516
  })
1371
1517
  }
1518
+
1519
+ async function setDefaultScrapeOptions() {
1520
+ return {
1521
+ tags_to_extract: ["body"],
1522
+ unwanted_tags: [],
1523
+ unwanted_classnames: []
1524
+ }
1525
+ }
1526
+
1527
+ async function setCustomScrapeOptions(options) {
1528
+ if (!options) {
1529
+ options = await setDefaultScrapeOptions();
1530
+ } else {
1531
+ if (!options.tags_to_extract || options.tags_to_extract.length == 0) {
1532
+ options.tags_to_extract = ["body"];
1533
+ }
1534
+ if (!options.unwanted_tags) {
1535
+ options.unwanted_tags = [];
1536
+ }
1537
+ if (!options.unwanted_classnames) {
1538
+ options.unwanted_classnames = [];
1539
+ }
1540
+ }
1541
+ }
1372
1542
  /**
1373
1543
  * ****************************************
1374
1544
  * Utils Methods Section - End
@@ -1,11 +1,13 @@
1
1
  var winston = require('../config/winston');
2
2
  const axios = require("axios").default;
3
3
  require('dotenv').config();
4
+ const jwt = require("jsonwebtoken")
4
5
 
5
6
  let openai_endpoint = process.env.OPENAI_ENDPOINT;
6
7
  let kb_endpoint = process.env.KB_ENDPOINT;
7
8
  let kb_endpoint_train = process.env.KB_ENDPOINT_TRAIN;
8
9
  let kb_endpoint_qa = process.env.KB_ENDPOINT_QA;
10
+ let secret = process.env.JWT_SECRET_KEY;
9
11
 
10
12
  class OpenaiService {
11
13
 
@@ -162,13 +164,15 @@ class OpenaiService {
162
164
  })
163
165
  }
164
166
 
165
- getContentChunks(namespace_id, content_id) {
167
+ getContentChunks(namespace_id, content_id, engine) {
166
168
  winston.info("[OPENAI SERVICE] kb endpoint: " + kb_endpoint_train);
167
169
  winston.info(kb_endpoint_train + "/id/" + content_id + "/namespace/" + namespace_id)
168
170
  return new Promise((resolve, reject) => {
169
171
 
172
+ let payload = { engine: engine };
173
+ let token = jwt.sign(payload, secret);
170
174
  axios({
171
- url: kb_endpoint_train + "/id/" + content_id + "/namespace/" + namespace_id,
175
+ url: kb_endpoint_train + "/id/" + content_id + "/namespace/" + namespace_id + "/" + token,
172
176
  headers: {
173
177
  'Content-Type': 'application/json'
174
178
  },
package/test/kbRoute.js CHANGED
@@ -58,7 +58,6 @@ describe('KbRoute', () => {
58
58
  expect(res.body.length).to.equal(1);
59
59
 
60
60
  let namespace_id = res.body[0].id;
61
- console.log("namespace_id: ", namespace_id);
62
61
 
63
62
  let kb = {
64
63
  name: "example_name5",
@@ -93,6 +92,128 @@ describe('KbRoute', () => {
93
92
 
94
93
  })
95
94
 
95
+ it('create-new-text-kb', (done) => {
96
+
97
+ var email = "test-signup-" + Date.now() + "@email.com";
98
+ var pwd = "pwd";
99
+
100
+ userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
101
+ projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
102
+
103
+ chai.request(server)
104
+ .get('/' + savedProject._id + '/kb/namespace/all')
105
+ .auth(email, pwd)
106
+ .end((err, res) => {
107
+
108
+ if (err) { console.error("err: ", err); }
109
+ if (log) { console.log("get namespaces res.body: ", res.body); }
110
+
111
+ res.should.have.status(200);
112
+ expect(res.body.length).to.equal(1);
113
+
114
+ let namespace_id = res.body[0].id;
115
+ console.log("namespace_id: ", namespace_id);
116
+
117
+ let kb = {
118
+ name: "example_text1",
119
+ type: "text",
120
+ source: "example_text1",
121
+ content: "Example text",
122
+ namespace: namespace_id
123
+ }
124
+
125
+ chai.request(server)
126
+ .post('/' + savedProject._id + '/kb')
127
+ .auth(email, pwd)
128
+ .send(kb) // can be empty
129
+ .end((err, res) => {
130
+
131
+ if (err) { console.error("err: ", err); }
132
+ if (log) { console.log("create kb res.body: ", res.body); }
133
+ console.log("create kb res.body: ", res.body);
134
+ res.should.have.status(200);
135
+ res.body.should.be.a('object');
136
+ expect(res.body.value.id_project).to.equal(res.body.value.namespace)
137
+ expect(res.body.value.name).to.equal("example_text1")
138
+ expect(res.body.value.type).to.equal("text")
139
+ expect(res.body.value.source).to.equal("example_text1")
140
+ expect(res.body.value.status).to.equal(-1)
141
+ expect(typeof res.body.value.scrape_type === "undefined").to.be.true;
142
+ expect(typeof res.body.value.scrape_options === "undefined").to.be.true;
143
+
144
+
145
+ done();
146
+ })
147
+ })
148
+ });
149
+ });
150
+
151
+ })
152
+
153
+ it('get-kb-chunks', (done) => {
154
+
155
+ var email = "test-signup-" + Date.now() + "@email.com";
156
+ var pwd = "pwd";
157
+
158
+ userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
159
+ projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
160
+
161
+ chai.request(server)
162
+ .get('/' + savedProject._id + '/kb/namespace/all')
163
+ .auth(email, pwd)
164
+ .end((err, res) => {
165
+
166
+ if (err) { console.error("err: ", err); }
167
+ if (log) { console.log("get namespaces res.body: ", res.body); }
168
+
169
+ res.should.have.status(200);
170
+ expect(res.body.length).to.equal(1);
171
+
172
+ let namespace_id = res.body[0].id;
173
+
174
+ let kb = {
175
+ name: "example_text1",
176
+ type: "text",
177
+ source: "example_text1",
178
+ content: "Example text",
179
+ namespace: namespace_id
180
+ }
181
+
182
+ chai.request(server)
183
+ .post('/' + savedProject._id + '/kb')
184
+ .auth(email, pwd)
185
+ .send(kb) // can be empty
186
+ .end((err, res) => {
187
+
188
+ if (err) { console.error("err: ", err); }
189
+ if (log) { console.log("create kb res.body: ", res.body); }
190
+ console.log("create kb res.body: ", res.body);
191
+ res.should.have.status(200);
192
+ res.body.should.be.a('object');
193
+
194
+ let content_id = res.body.value._id;
195
+
196
+ chai.request(server)
197
+ .get('/' + savedProject._id + '/kb/namespace/' + namespace_id + '/chunks/' + content_id)
198
+ .auth(email, pwd)
199
+ .end((err, res) => {
200
+
201
+ if (err) { console.error("err: ", err )};
202
+ if (log) { console.log("res.body: ", res.body )};
203
+
204
+ res.should.have.status(200);
205
+ //expect(res.body.length).to.equal(1);
206
+
207
+ done();
208
+ })
209
+
210
+ })
211
+ })
212
+ });
213
+ });
214
+
215
+ })
216
+
96
217
  it('get-with-queries', (done) => {
97
218
 
98
219
  var email = "test-signup-" + Date.now() + "@email.com";
@@ -172,14 +293,14 @@ describe('KbRoute', () => {
172
293
  if (log) { console.log("create kb3 res.body: ", res.body); }
173
294
  res.should.have.status(200);
174
295
 
175
- let query = "?status=100&type=url&limit=5&page=0&direction=-1&sortField=updatedAt&search=example&namespace=" + namespace_id;
176
- //let query = "";
177
- console.log("query: ", query);
296
+ let query = "?status=-1&type=url&limit=5&page=0&direction=-1&sortField=updatedAt&search=example&namespace=" + namespace_id;
297
+ //let query = "?namespace=" + namespace_id;
178
298
 
179
299
  chai.request(server)
180
300
  .get('/' + savedProject._id + "/kb" + query)
181
301
  .auth(email, pwd)
182
302
  .end((err, res) => {
303
+ if (err) { console.error("err: ", err)}
183
304
  if (log) { console.log("getall res.body: ", res.body); }
184
305
  res.should.have.status(200);
185
306
  res.body.should.be.a('object');
@@ -187,7 +308,7 @@ describe('KbRoute', () => {
187
308
  expect(res.body.kbs.length).to.equal(2);
188
309
  expect(res.body.count).to.equal(2);
189
310
  res.body.query.should.be.a('object');
190
- expect(res.body.query.status).to.equal(100);
311
+ expect(res.body.query.status).to.equal(-1);
191
312
  expect(res.body.query.limit).to.equal(5);
192
313
  expect(res.body.query.page).to.equal(0);
193
314
  expect(res.body.query.direction).to.equal(-1);
@@ -255,7 +376,6 @@ describe('KbRoute', () => {
255
376
  let namespace_id = "fakenamespaceid";
256
377
 
257
378
  let query = "?status=100&type=url&limit=5&page=0&direction=-1&sortField=updatedAt&search=example&namespace=" + namespace_id;
258
- console.log("query: ", query);
259
379
 
260
380
  chai.request(server)
261
381
  .get('/' + savedProject._id + "/kb" + query)
@@ -308,7 +428,6 @@ describe('KbRoute', () => {
308
428
 
309
429
  if (err) { console.error("err: ", err); }
310
430
  if (log) { console.log("res.body: ", res.body) }
311
- console.log("res.body: ", res.body)
312
431
 
313
432
  res.should.have.status(200);
314
433
 
@@ -357,6 +476,7 @@ describe('KbRoute', () => {
357
476
 
358
477
  }).timeout(10000)
359
478
 
479
+
360
480
  /**
361
481
  * If you try to add content to a namespace that does not belong to the selected project and
362
482
  * the project has at least one namesapce, it returns 403 forbidden.
@@ -435,6 +555,7 @@ describe('KbRoute', () => {
435
555
 
436
556
  if (err) { console.error("err: ", err); }
437
557
  if (log) { console.log("res.body: ", res.body) }
558
+ console.log("res.body: ", res.body)
438
559
 
439
560
  res.should.have.status(200);
440
561
  expect(res.body.length).to.equal(4)
@@ -448,6 +569,97 @@ describe('KbRoute', () => {
448
569
 
449
570
  }).timeout(10000)
450
571
 
572
+ it('add-multiple-urls-with-scrape-option-success-type-4', (done) => {
573
+
574
+ var email = "test-signup-" + Date.now() + "@email.com";
575
+ var pwd = "pwd";
576
+
577
+ userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
578
+ projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
579
+
580
+ chai.request(server)
581
+ .get('/' + savedProject._id + '/kb/namespace/all')
582
+ .auth(email, pwd)
583
+ .end((err, res) => {
584
+
585
+ if (err) { console.error("err: ", err); }
586
+ if (log) { console.log("res.body: ", res.body) }
587
+
588
+ res.should.have.status(200)
589
+ expect(res.body.length).to.equal(1);
590
+
591
+ let namespace_id = res.body[0].id;
592
+
593
+ chai.request(server)
594
+ .post('/' + savedProject._id + '/kb/multi?namespace=' + namespace_id)
595
+ .auth(email, pwd)
596
+ .send({ list:["https://gethelp.tiledesk.com/article"], scrape_type: 4, scrape_options: { tags_to_extract: ["article","p"], unwanted_tags:["script","style"], unwanted_classnames:["header","related-articles"]}})
597
+ .end((err, res) => {
598
+
599
+ if (err) { console.error("err: ", err); }
600
+ if (log) { console.log("res.body: ", res.body) }
601
+ console.log("res.body: ", res.body)
602
+ res.should.have.status(200);
603
+ expect(res.body.length).to.equal(1)
604
+ expect(res.body[0].scrape_type).to.equal(4)
605
+ expect(typeof res.body[0].scrape_options === "undefined").to.be.false;
606
+ expect(res.body[0].scrape_options.tags_to_extract.length).to.equal(2);
607
+ expect(res.body[0].scrape_options.unwanted_tags.length).to.equal(2);
608
+ expect(res.body[0].scrape_options.unwanted_classnames.length).to.equal(2);
609
+
610
+ done();
611
+
612
+ })
613
+ })
614
+ });
615
+ });
616
+
617
+ }).timeout(10000)
618
+
619
+ it('add-multiple-urls-with-scrape-option-success-type-3', (done) => {
620
+
621
+ var email = "test-signup-" + Date.now() + "@email.com";
622
+ var pwd = "pwd";
623
+
624
+ userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
625
+ projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
626
+
627
+ chai.request(server)
628
+ .get('/' + savedProject._id + '/kb/namespace/all')
629
+ .auth(email, pwd)
630
+ .end((err, res) => {
631
+
632
+ if (err) { console.error("err: ", err); }
633
+ if (log) { console.log("res.body: ", res.body) }
634
+
635
+ res.should.have.status(200)
636
+ expect(res.body.length).to.equal(1);
637
+
638
+ let namespace_id = res.body[0].id;
639
+
640
+ chai.request(server)
641
+ .post('/' + savedProject._id + '/kb/multi?namespace=' + namespace_id)
642
+ .auth(email, pwd)
643
+ .send({ list:["https://gethelp.tiledesk.com/article"], scrape_type: 3 })
644
+ .end((err, res) => {
645
+
646
+ if (err) { console.error("err: ", err); }
647
+ if (log) { console.log("res.body: ", res.body) }
648
+ console.log("res.body: ", res.body)
649
+ res.should.have.status(200);
650
+ expect(res.body.length).to.equal(1)
651
+ expect(res.body[0].scrape_type).to.equal(3)
652
+ expect(typeof res.body[0].scrape_options === "undefined").to.be.true;
653
+
654
+ done();
655
+
656
+ })
657
+ })
658
+ });
659
+ });
660
+
661
+ }).timeout(10000)
662
+
451
663
  it('expand-sitemap', (done) => {
452
664
 
453
665
  var email = "test-signup-" + Date.now() + "@email.com";
@@ -1098,41 +1310,41 @@ describe('KbRoute', () => {
1098
1310
  // }).timeout(10000)
1099
1311
 
1100
1312
  // Ask KB
1101
- // it('askkb-key-from-env', (done) => {
1313
+ it('askkb-key-from-env', (done) => {
1102
1314
 
1103
- // var email = "test-signup-" + Date.now() + "@email.com";
1104
- // var pwd = "pwd";
1315
+ var email = "test-signup-" + Date.now() + "@email.com";
1316
+ var pwd = "pwd";
1105
1317
 
1106
- // userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
1107
- // projectService.create("test-kb-qa", savedUser._id).then((savedProject) => {
1318
+ userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
1319
+ projectService.create("test-kb-qa", savedUser._id).then((savedProject) => {
1108
1320
 
1109
- // chai.request(server)
1110
- // .get('/' + savedProject._id + '/kb/namespace/all')
1111
- // .auth(email, pwd)
1112
- // .end((err, res) => {
1321
+ chai.request(server)
1322
+ .get('/' + savedProject._id + '/kb/namespace/all')
1323
+ .auth(email, pwd)
1324
+ .end((err, res) => {
1113
1325
 
1114
- // if (err) { console.error("err: ", err); }
1115
- // if (log) { console.log("get all namespaces res.body: ", res.body); }
1116
-
1117
- // console.log("namespace created..")
1326
+ if (err) { console.error("err: ", err); }
1327
+ if (log) { console.log("get all namespaces res.body: ", res.body); }
1118
1328
 
1119
- // chai.request(server)
1120
- // .post('/' + savedProject._id + "/kb/qa")
1121
- // .auth(email, pwd)
1122
- // .send({ model: "gpt-4o", namespace: savedProject._id, question: "sample question" })
1123
- // .end((err, res) => {
1329
+ console.log("namespace created..")
1124
1330
 
1125
- // if (err) { console.error("err: ", err) };
1126
- // if (log) { console.log("res.body: ", res.body) };
1127
- // console.log("res.body: ", res.body)
1128
- // done();
1129
- // })
1331
+ chai.request(server)
1332
+ .post('/' + savedProject._id + "/kb/qa")
1333
+ .auth(email, pwd)
1334
+ .send({ model: "gpt-4o", namespace: savedProject._id, question: "sample question", advancedPrompt: true, system_context: "You are a robot coming from future" })
1335
+ .end((err, res) => {
1130
1336
 
1337
+ if (err) { console.error("err: ", err) };
1338
+ if (log) { console.log("res.body: ", res.body) };
1339
+ console.log("res.body: ", res.body)
1340
+ done();
1341
+ })
1131
1342
 
1132
- // })
1133
- // })
1134
- // })
1135
- // }).timeout(10000)
1343
+
1344
+ })
1345
+ })
1346
+ })
1347
+ }).timeout(10000)
1136
1348
 
1137
1349
 
1138
1350
  it('webhook', (done) => {
@@ -1215,7 +1427,7 @@ describe('KbRoute', () => {
1215
1427
  * Get all namespaces of a project.
1216
1428
  * If there isn't namespaces for a project_id, the default namespace is created and returned.
1217
1429
  */
1218
- it('get-namespaces', (done) => {
1430
+ it('get-namespaces-1', (done) => {
1219
1431
 
1220
1432
  var email = "test-signup-" + Date.now() + "@email.com";
1221
1433
  var pwd = "pwd";
@@ -1238,6 +1450,8 @@ describe('KbRoute', () => {
1238
1450
  //expect(res.body[0]._id).to.equal(undefined);
1239
1451
  expect(res.body[0].id).to.equal(savedProject._id.toString());
1240
1452
  expect(res.body[0].name).to.equal("Default");
1453
+ should.exist(res.body[0].engine)
1454
+ expect(res.body[0].engine.name).to.equal('pinecone')
1241
1455
 
1242
1456
  done();
1243
1457
 
@@ -1318,6 +1532,76 @@ describe('KbRoute', () => {
1318
1532
  });
1319
1533
  })
1320
1534
 
1535
+ it('create-namespaces-with-engine', (done) => {
1536
+
1537
+ var email = "test-signup-" + Date.now() + "@email.com";
1538
+ var pwd = "pwd";
1539
+
1540
+ userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
1541
+ projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
1542
+
1543
+ // Get all namespaces. Create default namespace and return.
1544
+ chai.request(server)
1545
+ .get('/' + savedProject._id + '/kb/namespace/all')
1546
+ .auth(email, pwd)
1547
+ .end((err, res) => {
1548
+
1549
+ if (err) { console.error("err: ", err); }
1550
+ if (log) { console.log("get all namespaces res.body: ", res.body); }
1551
+
1552
+ res.should.have.status(200);
1553
+ res.body.should.be.a('array');
1554
+ expect(res.body.length).to.equal(1);
1555
+ should.not.exist(res.body[0]._id);
1556
+ expect(res.body[0].id).to.equal(savedProject._id.toString());
1557
+ expect(res.body[0].name).to.equal("Default");
1558
+ should.exist(res.body[0].engine)
1559
+ expect(res.body[0].engine.name).to.equal('pinecone');
1560
+ expect(res.body[0].engine.type).to.equal('pod');
1561
+
1562
+ // Create another namespace
1563
+ chai.request(server)
1564
+ .post('/' + savedProject._id + '/kb/namespace')
1565
+ .auth(email, pwd)
1566
+ .send({ name: "MyCustomNamespace" })
1567
+ .end((err, res) => {
1568
+
1569
+ if (err) { console.error("err: ", err) }
1570
+ if (log) { console.log("create new namespace res.body: ", res.body) }
1571
+
1572
+ res.should.have.status(200);
1573
+ res.body.should.be.a('object');
1574
+ should.not.exist(res.body._id)
1575
+ should.exist(res.body.id)
1576
+ expect(res.body.name).to.equal('MyCustomNamespace');
1577
+ should.exist(res.body.engine)
1578
+ expect(res.body.engine.name).to.equal('pinecone');
1579
+ expect(res.body.engine.type).to.equal('pod');
1580
+
1581
+ // Get again all namespace. A new default namespace should not be created.
1582
+ chai.request(server)
1583
+ .get('/' + savedProject._id + '/kb/namespace/all')
1584
+ .auth(email, pwd)
1585
+ .end((err, res) => {
1586
+
1587
+ if (err) { console.error("err: ", err); }
1588
+ if (log) { console.log("get all namespaces res.body: ", res.body); }
1589
+
1590
+ res.should.have.status(200);
1591
+ res.body.should.be.a('array');
1592
+ expect(res.body.length).to.equal(2);
1593
+ should.not.exist(res.body[0]._id);
1594
+ should.not.exist(res.body[1]._id);
1595
+ should.exist(res.body[0].id);
1596
+ should.exist(res.body[1].id);
1597
+
1598
+ done();
1599
+ })
1600
+ })
1601
+ })
1602
+ });
1603
+ });
1604
+ })
1321
1605
 
1322
1606
  /**
1323
1607
  * Update namespaces
@@ -1346,7 +1630,6 @@ describe('KbRoute', () => {
1346
1630
  expect(res.body[0].name).to.equal("Default");
1347
1631
 
1348
1632
  let namespace_id = res.body[0].id;
1349
- console.log("namespace_id: ", namespace_id);
1350
1633
 
1351
1634
  let new_settings = {
1352
1635
  model: 'gpt-4o',
@@ -1411,7 +1694,6 @@ describe('KbRoute', () => {
1411
1694
  expect(res.body[0].name).to.equal("Default");
1412
1695
 
1413
1696
  let namespace_id = res.body[0].id;
1414
- console.log("namespace_id: ", namespace_id);
1415
1697
 
1416
1698
  // Update namespace
1417
1699
  chai.request(server)