@tiledesk/tiledesk-server 2.18.3 → 2.18.4
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/CHANGELOG.md +6 -0
- package/config/kb/situatedContext.js +1 -1
- package/models/kb_setting.js +5 -0
- package/package.json +2 -2
- package/routes/kb.js +50 -20
- package/routes/webhook.js +8 -4
- package/services/aiManager.js +12 -6
- package/test/kbRoute.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
|
7
7
|
|
|
8
|
+
# 2.18.4
|
|
9
|
+
- Added HyDE support for Knowledge Base Q&A
|
|
10
|
+
- Introduced Cache (cRag) functionality in Knowledge Base Q&A
|
|
11
|
+
- Enabled Situated Context for enhanced Knowledge Base content indexing
|
|
12
|
+
- Bumped tybot-connector version to 2.0.48
|
|
13
|
+
|
|
8
14
|
# 2.18.3
|
|
9
15
|
- Added permissions logic
|
|
10
16
|
- Added custom roles support
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
enable: process.env.SITUATED_CONTEXT_ENABLE === "true",
|
|
3
3
|
provider: process.env.SITUATED_CONTEXT_PROVIDER || "openai",
|
|
4
|
-
model: process.env.SITUATED_CONTEXT_MODEL || "gpt-
|
|
4
|
+
model: process.env.SITUATED_CONTEXT_MODEL || "gpt-5.4-nano",
|
|
5
5
|
api_key: ""
|
|
6
6
|
}
|
package/models/kb_setting.js
CHANGED
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.18.
|
|
4
|
+
"version": "2.18.4",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "node ./bin/www",
|
|
7
7
|
"pretest": "mongodb-runner start",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
|
50
50
|
"@tiledesk/tiledesk-sms-connector": "^0.1.13",
|
|
51
51
|
"@tiledesk/tiledesk-telegram-connector": "^0.1.14",
|
|
52
|
-
"@tiledesk/tiledesk-tybot-connector": "^2.0.
|
|
52
|
+
"@tiledesk/tiledesk-tybot-connector": "^2.0.48",
|
|
53
53
|
"@tiledesk/tiledesk-voice-twilio-connector": "^0.3.2",
|
|
54
54
|
"@tiledesk/tiledesk-vxml-connector": "^0.1.91",
|
|
55
55
|
"@tiledesk/tiledesk-whatsapp-connector": "1.0.26",
|
package/routes/kb.js
CHANGED
|
@@ -121,7 +121,8 @@ function normalizeEmbedding(embedding) {
|
|
|
121
121
|
return { ...normalizedEmbedding };
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
function normalizeSituatedContext() {
|
|
124
|
+
function normalizeSituatedContext(enable = false) {
|
|
125
|
+
situatedContext.enable = enable;
|
|
125
126
|
return situatedContext.enable
|
|
126
127
|
? {
|
|
127
128
|
...situatedContext,
|
|
@@ -199,6 +200,11 @@ router.post('/scrape/single', async (req, res) => {
|
|
|
199
200
|
})
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
let situated_context;
|
|
204
|
+
if (sitemapKb.situated_context && sitemapKb.situated_context === true && sitemapKb.scrape_type === 0) {
|
|
205
|
+
situated_context = normalizeSituatedContext(true);
|
|
206
|
+
}
|
|
207
|
+
|
|
202
208
|
if (addedUrls.length > 0) {
|
|
203
209
|
const options = {
|
|
204
210
|
sitemap_origin_id: sitemapKb._id,
|
|
@@ -206,7 +212,8 @@ router.post('/scrape/single', async (req, res) => {
|
|
|
206
212
|
scrape_type: sitemapKb.scrape_type,
|
|
207
213
|
scrape_options: sitemapKb.scrape_options,
|
|
208
214
|
refresh_rate: sitemapKb.refresh_rate,
|
|
209
|
-
tags: sitemapKb.tags
|
|
215
|
+
tags: sitemapKb.tags,
|
|
216
|
+
...(situated_context && { situated_context: situated_context }),
|
|
210
217
|
}
|
|
211
218
|
aiManager.addMultipleUrls(namespace, addedUrls, options).catch((err) => {
|
|
212
219
|
winston.error("(webhook) error adding multiple urls contents: ", err);
|
|
@@ -263,9 +270,8 @@ router.post('/scrape/single', async (req, res) => {
|
|
|
263
270
|
json.hybrid = true;
|
|
264
271
|
}
|
|
265
272
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
json.situated_context = situated_context;
|
|
273
|
+
if (json.situated_context && json.situated_context === true && json.scrape_type === 0) {
|
|
274
|
+
json.situated_context = normalizeSituatedContext(true);
|
|
269
275
|
}
|
|
270
276
|
|
|
271
277
|
winston.verbose("/scrape/single json: ", json);
|
|
@@ -447,12 +453,11 @@ router.post('/qa', async (req, res) => {
|
|
|
447
453
|
}
|
|
448
454
|
|
|
449
455
|
data.stream = data.stream === true;
|
|
456
|
+
data.use_hyde = data.use_hyde === true;
|
|
457
|
+
data.use_cache = data.use_cache === true;
|
|
450
458
|
data.debug = true;
|
|
451
459
|
delete data.advancedPrompt;
|
|
452
460
|
winston.verbose("ask data: ", data);
|
|
453
|
-
|
|
454
|
-
console.log("data: ", data);
|
|
455
|
-
|
|
456
461
|
if (process.env.NODE_ENV === 'test') {
|
|
457
462
|
return res.status(200).send({ success: true, message: "Question skipped in test environment", data: data });
|
|
458
463
|
}
|
|
@@ -1591,7 +1596,7 @@ router.post('/', async (req, res) => {
|
|
|
1591
1596
|
const id_project = req.projectid;
|
|
1592
1597
|
const project = req.project
|
|
1593
1598
|
|
|
1594
|
-
const { name, type, source, content, refresh_rate, scrape_type, scrape_options, tags } = req.body;
|
|
1599
|
+
const { name, type, source, content, refresh_rate, scrape_type, scrape_options, tags, situated_context } = req.body;
|
|
1595
1600
|
const namespace_id = req.body?.namespace;
|
|
1596
1601
|
|
|
1597
1602
|
if (!namespace_id) {
|
|
@@ -1643,6 +1648,10 @@ router.post('/', async (req, res) => {
|
|
|
1643
1648
|
new_kb.tags = tags;
|
|
1644
1649
|
}
|
|
1645
1650
|
|
|
1651
|
+
if (situated_context && situated_context === true && (type !== "url" || scrape_type === 0)) {
|
|
1652
|
+
new_kb.situated_context = situated_context;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1646
1655
|
winston.debug("adding kb: ", new_kb);
|
|
1647
1656
|
|
|
1648
1657
|
KB.findOneAndUpdate({ id_project, type, source }, new_kb, { upsert: true, new: true, rawResult: true }, async (err, raw_content) => {
|
|
@@ -1661,7 +1670,7 @@ router.post('/', async (req, res) => {
|
|
|
1661
1670
|
const embedding = normalizeEmbedding(namespace.embedding);
|
|
1662
1671
|
embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
|
|
1663
1672
|
|
|
1664
|
-
const
|
|
1673
|
+
const situated_context_obj = normalizeSituatedContext(saved_kb.situated_context);
|
|
1665
1674
|
|
|
1666
1675
|
const json = {
|
|
1667
1676
|
id: saved_kb._id,
|
|
@@ -1673,7 +1682,7 @@ router.post('/', async (req, res) => {
|
|
|
1673
1682
|
hybrid: namespace.hybrid,
|
|
1674
1683
|
engine: namespace.engine || default_engine,
|
|
1675
1684
|
embedding: embedding,
|
|
1676
|
-
...(
|
|
1685
|
+
...(situated_context_obj && { situated_context: situated_context_obj }),
|
|
1677
1686
|
...(saved_kb.scrape_type && { scrape_type: saved_kb.scrape_type }),
|
|
1678
1687
|
...(saved_kb.scrape_options && { parameters_scrape_type_4: saved_kb.scrape_options }),
|
|
1679
1688
|
...(saved_kb.tags && { tags: saved_kb.tags }),
|
|
@@ -1705,7 +1714,7 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
|
|
|
1705
1714
|
|
|
1706
1715
|
const id_project = req.projectid;
|
|
1707
1716
|
const project = req.project;
|
|
1708
|
-
let { refresh_rate = 'never', scrape_type = 2, scrape_options } = req.body;
|
|
1717
|
+
let { refresh_rate = 'never', scrape_type = 2, scrape_options, situated_context } = req.body;
|
|
1709
1718
|
let tags = parseStringArrayField(req.body.tags);
|
|
1710
1719
|
|
|
1711
1720
|
|
|
@@ -1748,6 +1757,7 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
|
|
|
1748
1757
|
scrape_type,
|
|
1749
1758
|
scrape_options,
|
|
1750
1759
|
refresh_rate,
|
|
1760
|
+
...(situated_context && situated_context === true && scrape_type === 0 ? { situated_context: true } : {}),
|
|
1751
1761
|
...(Array.isArray(tags) && tags.length > 0 ? { tags } : {})
|
|
1752
1762
|
}
|
|
1753
1763
|
|
|
@@ -1772,6 +1782,11 @@ router.post('/csv', upload.single('uploadFile'), async (req, res) => {
|
|
|
1772
1782
|
const { delimiter = ';' } = req.body;
|
|
1773
1783
|
let tags = parseStringArrayField(req.body.tags);
|
|
1774
1784
|
|
|
1785
|
+
let situated_context = false;
|
|
1786
|
+
if (req.body.situated_context) {
|
|
1787
|
+
situated_context = req.body.situated_context === true || req.body.situated_context === "true";
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1775
1790
|
|
|
1776
1791
|
let namespace;
|
|
1777
1792
|
try {
|
|
@@ -1799,6 +1814,7 @@ router.post('/csv', upload.single('uploadFile'), async (req, res) => {
|
|
|
1799
1814
|
content: question + "\n" + answer,
|
|
1800
1815
|
namespace: namespace_id,
|
|
1801
1816
|
status: -1,
|
|
1817
|
+
...(situated_context && { situated_context: situated_context }),
|
|
1802
1818
|
...(Array.isArray(tags) && tags.length > 0 ? { tags } : {})
|
|
1803
1819
|
})
|
|
1804
1820
|
})
|
|
@@ -1830,16 +1846,20 @@ router.post('/csv', upload.single('uploadFile'), async (req, res) => {
|
|
|
1830
1846
|
let embedding = normalizeEmbedding(namespace.embedding);
|
|
1831
1847
|
embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
|
|
1832
1848
|
let hybrid = namespace.hybrid;
|
|
1833
|
-
const situated_context = normalizeSituatedContext();
|
|
1834
1849
|
|
|
1835
|
-
let
|
|
1850
|
+
let situated_context_obj;
|
|
1851
|
+
if (situated_context) {
|
|
1852
|
+
situated_context_obj = normalizeSituatedContext(situated_context);
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, situated_context, ...keepAttrs }) => keepAttrs)
|
|
1836
1856
|
resources = resources.map(({ _id, ...rest}) => {
|
|
1837
1857
|
return {
|
|
1838
1858
|
id: _id,
|
|
1839
1859
|
webhook: webhook,
|
|
1840
1860
|
embedding: embedding,
|
|
1841
1861
|
engine: engine,
|
|
1842
|
-
...(
|
|
1862
|
+
...(situated_context_obj && { situated_context: situated_context_obj }),
|
|
1843
1863
|
...rest
|
|
1844
1864
|
};
|
|
1845
1865
|
})
|
|
@@ -1891,7 +1911,7 @@ router.post('/sitemap/import', async (req, res) => {
|
|
|
1891
1911
|
const id_project = req.projectid;
|
|
1892
1912
|
const namespace_id = req.query.namespace;
|
|
1893
1913
|
|
|
1894
|
-
let { type, source, refresh_rate = 'never', scrape_type = 2, scrape_options, tags } = req.body;
|
|
1914
|
+
let { type, source, refresh_rate = 'never', scrape_type = 2, scrape_options, tags, situated_context } = req.body;
|
|
1895
1915
|
if (scrape_type === 2 && !scrape_options) {
|
|
1896
1916
|
scrape_options = aiManager.setDefaultScrapeOptions();
|
|
1897
1917
|
}
|
|
@@ -1957,6 +1977,7 @@ router.post('/sitemap/import', async (req, res) => {
|
|
|
1957
1977
|
scrape_type,
|
|
1958
1978
|
scrape_options,
|
|
1959
1979
|
refresh_rate,
|
|
1980
|
+
...(situated_context && situated_context === true && scrape_type === 0 ? { situated_context: true } : {}),
|
|
1960
1981
|
...(Array.isArray(tags) && tags.length > 0 ? { tags } : {})
|
|
1961
1982
|
}
|
|
1962
1983
|
|
|
@@ -1974,7 +1995,8 @@ router.post('/sitemap/import', async (req, res) => {
|
|
|
1974
1995
|
scrape_type,
|
|
1975
1996
|
scrape_options,
|
|
1976
1997
|
refresh_rate,
|
|
1977
|
-
...(Array.isArray(tags) && tags.length > 0 ? { tags } : {})
|
|
1998
|
+
...(Array.isArray(tags) && tags.length > 0 ? { tags } : {}),
|
|
1999
|
+
...(situated_context && situated_context === true && scrape_type === 0 ? { situated_context: true } : {}),
|
|
1978
2000
|
}
|
|
1979
2001
|
|
|
1980
2002
|
try {
|
|
@@ -1998,7 +2020,7 @@ router.put('/:kb_id', async (req, res) => {
|
|
|
1998
2020
|
const project = req.project;
|
|
1999
2021
|
const kb_id = req.params.kb_id;
|
|
2000
2022
|
|
|
2001
|
-
const { name, type, source, content, refresh_rate, scrape_type, scrape_options, tags } = req.body;
|
|
2023
|
+
const { name, type, source, content, refresh_rate, scrape_type, scrape_options, tags, situated_context } = req.body;
|
|
2002
2024
|
const namespace_id = req.body.namespace;
|
|
2003
2025
|
|
|
2004
2026
|
if (!namespace_id) {
|
|
@@ -2065,6 +2087,10 @@ router.put('/:kb_id', async (req, res) => {
|
|
|
2065
2087
|
return res.status(500).send({ success: false, error: err });
|
|
2066
2088
|
}
|
|
2067
2089
|
|
|
2090
|
+
if (situated_context && situated_context === true && scrape_type === 0) {
|
|
2091
|
+
situated_context = true;
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2068
2094
|
let new_content = {
|
|
2069
2095
|
id_project,
|
|
2070
2096
|
name,
|
|
@@ -2096,6 +2122,10 @@ router.put('/:kb_id', async (req, res) => {
|
|
|
2096
2122
|
new_content.tags = tags;
|
|
2097
2123
|
}
|
|
2098
2124
|
|
|
2125
|
+
if (situated_context && situated_context === true && scrape_type === 0) {
|
|
2126
|
+
new_content.situated_context = situated_context;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2099
2129
|
winston.debug("Update content. New content: ", new_content);
|
|
2100
2130
|
|
|
2101
2131
|
let updated_content;
|
|
@@ -2109,7 +2139,7 @@ router.put('/:kb_id', async (req, res) => {
|
|
|
2109
2139
|
const embedding = normalizeEmbedding(namespace.embedding);
|
|
2110
2140
|
embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
|
|
2111
2141
|
let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
|
|
2112
|
-
const
|
|
2142
|
+
const situated_context_obj = normalizeSituatedContext(updated_content.situated_context);
|
|
2113
2143
|
|
|
2114
2144
|
const json = {
|
|
2115
2145
|
id: updated_content._id,
|
|
@@ -2121,7 +2151,7 @@ router.put('/:kb_id', async (req, res) => {
|
|
|
2121
2151
|
hybrid: namespace.hybrid,
|
|
2122
2152
|
engine: namespace.engine || default_engine,
|
|
2123
2153
|
embedding: embedding,
|
|
2124
|
-
...(
|
|
2154
|
+
...(situated_context_obj && { situated_context: situated_context_obj }),
|
|
2125
2155
|
...(updated_content.scrape_type && { scrape_type: updated_content.scrape_type }),
|
|
2126
2156
|
...(updated_content.scrape_options && { parameters_scrape_type_4: updated_content.scrape_options }),
|
|
2127
2157
|
...(updated_content.tags && { tags: updated_content.tags }),
|
package/routes/webhook.js
CHANGED
|
@@ -148,7 +148,11 @@ router.post('/kb/reindex', async (req, res) => {
|
|
|
148
148
|
sitemap_origin: kb.source,
|
|
149
149
|
scrape_type: kb.scrape_type,
|
|
150
150
|
scrape_options: kb.scrape_options,
|
|
151
|
-
refresh_rate: kb.refresh_rate
|
|
151
|
+
refresh_rate: kb.refresh_rate,
|
|
152
|
+
...(kb.tags ? { tags: kb.tags } : {}),
|
|
153
|
+
...(kb.situated_context === true && (kb.scrape_type === 0 || kb.scrape_type === '0')
|
|
154
|
+
? { situated_context: true }
|
|
155
|
+
: {}),
|
|
152
156
|
}
|
|
153
157
|
aiManager.addMultipleUrls(namespace, addedUrls, options).catch((err) => {
|
|
154
158
|
winston.error("(webhook) error adding multiple urls contents: ", err);
|
|
@@ -198,9 +202,9 @@ router.post('/kb/reindex', async (req, res) => {
|
|
|
198
202
|
embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
|
|
199
203
|
json.embedding = embedding;
|
|
200
204
|
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
203
|
-
json.situated_context =
|
|
205
|
+
const situated_context_obj = aiManager.normalizeSituatedContext(kb.situated_context);
|
|
206
|
+
if (situated_context_obj) {
|
|
207
|
+
json.situated_context = situated_context_obj;
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
let resources = [];
|
package/services/aiManager.js
CHANGED
|
@@ -52,6 +52,7 @@ jobManagerHybrid.connectAndStartPublisher((status, error) => {
|
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
|
|
55
56
|
class AiManager {
|
|
56
57
|
|
|
57
58
|
constructor() { }
|
|
@@ -74,6 +75,7 @@ class AiManager {
|
|
|
74
75
|
...(options.sitemap_origin_id && { sitemap_origin_id: options.sitemap_origin_id }),
|
|
75
76
|
...(options.sitemap_origin && { sitemap_origin: options.sitemap_origin }),
|
|
76
77
|
...(options.tags && { tags: options.tags }),
|
|
78
|
+
...(options.situated_context && { situated_context: options.situated_context }),
|
|
77
79
|
}
|
|
78
80
|
return kb;
|
|
79
81
|
})
|
|
@@ -95,11 +97,14 @@ class AiManager {
|
|
|
95
97
|
let embedding = namespace.embedding || default_embedding;
|
|
96
98
|
embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
|
|
97
99
|
|
|
98
|
-
let situated_context
|
|
100
|
+
let situated_context;
|
|
101
|
+
if (options.situated_context) {
|
|
102
|
+
situated_context = this.normalizeSituatedContext(options.situated_context);
|
|
103
|
+
}
|
|
99
104
|
|
|
100
105
|
let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
|
|
101
106
|
|
|
102
|
-
let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
|
|
107
|
+
let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, situated_context, ...keepAttrs }) => keepAttrs)
|
|
103
108
|
resources = resources.map(({ _id, scrape_options, ...rest }) => {
|
|
104
109
|
return {
|
|
105
110
|
id: _id,
|
|
@@ -132,8 +137,6 @@ class AiManager {
|
|
|
132
137
|
async scheduleSitemap(namespace, sitemap_content, options) {
|
|
133
138
|
return new Promise((resolve, reject) => {
|
|
134
139
|
|
|
135
|
-
const situated_context = this.normalizeSituatedContext();
|
|
136
|
-
|
|
137
140
|
let kb = {
|
|
138
141
|
id: sitemap_content._id,
|
|
139
142
|
source: sitemap_content.source,
|
|
@@ -144,7 +147,7 @@ class AiManager {
|
|
|
144
147
|
engine: namespace.engine,
|
|
145
148
|
embedding: namespace.embedding,
|
|
146
149
|
hybrid: namespace.hybrid,
|
|
147
|
-
...(situated_context && { situated_context }),
|
|
150
|
+
...(options.situated_context && { situated_context: options.situated_context }),
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
if (process.env.NODE_ENV === 'test') {
|
|
@@ -190,6 +193,8 @@ class AiManager {
|
|
|
190
193
|
throw err;
|
|
191
194
|
}
|
|
192
195
|
|
|
196
|
+
|
|
197
|
+
|
|
193
198
|
// Recreate all url contents with sitemap_origin_id
|
|
194
199
|
let result;
|
|
195
200
|
try {
|
|
@@ -567,7 +572,8 @@ class AiManager {
|
|
|
567
572
|
})
|
|
568
573
|
}
|
|
569
574
|
|
|
570
|
-
normalizeSituatedContext() {
|
|
575
|
+
normalizeSituatedContext(enable = false) {
|
|
576
|
+
situatedContext.enable = enable;
|
|
571
577
|
return situatedContext.enable
|
|
572
578
|
? {
|
|
573
579
|
...situatedContext,
|
package/test/kbRoute.js
CHANGED
|
@@ -1011,6 +1011,7 @@ describe('KbRoute', () => {
|
|
|
1011
1011
|
.auth(email, pwd)
|
|
1012
1012
|
//.set('Content-Type', 'text/csv')
|
|
1013
1013
|
.field('delimiter', ';')
|
|
1014
|
+
.field('situated_context', true)
|
|
1014
1015
|
.field('tags', JSON.stringify(['tag1', 'tag2']))
|
|
1015
1016
|
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './fixtures/example-kb-faqs.csv')), 'example-kb-faqs.csv')
|
|
1016
1017
|
.end((err, res) => {
|