wingbot 3.35.0 → 3.36.1
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 +2 -2
- package/src/Ai.js +49 -11
- package/src/AiMatching.js +32 -8
- package/src/BotApp.js +5 -3
- package/src/Processor.js +1 -1
- package/src/Request.js +3 -2
- package/src/utils/stateData.js +11 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wingbot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.36.1",
|
|
4
4
|
"description": "Enterprise Messaging Bot Conversation Engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"eslint-plugin-react": "^7.29.4",
|
|
47
47
|
"graphql-markdown": "^6.0.0",
|
|
48
48
|
"jsdoc-to-markdown": "^7.1.1",
|
|
49
|
-
"mocha": "^
|
|
49
|
+
"mocha": "^10.0.0",
|
|
50
50
|
"nyc": "^15.1.0",
|
|
51
51
|
"rimraf": "^3.0.2",
|
|
52
52
|
"sinon": "^13.0.1",
|
package/src/Ai.js
CHANGED
|
@@ -40,6 +40,8 @@ let uq = 1;
|
|
|
40
40
|
|
|
41
41
|
/** @typedef {import('./Request').IntentAction} IntentAction */
|
|
42
42
|
/** @typedef {import('./Request')} Request */
|
|
43
|
+
/** @typedef {import('./Responder')} Responder */
|
|
44
|
+
/** @typedef {import('./wingbot/CachedModel').Result} Result */
|
|
43
45
|
/** @typedef {import('./wingbot/CustomEntityDetectionModel').Phrases} Phrases */
|
|
44
46
|
|
|
45
47
|
/**
|
|
@@ -203,6 +205,10 @@ class Ai {
|
|
|
203
205
|
return model;
|
|
204
206
|
}
|
|
205
207
|
|
|
208
|
+
get localEnhancement () {
|
|
209
|
+
return (1 - this.confidence) / 2;
|
|
210
|
+
}
|
|
211
|
+
|
|
206
212
|
async processSetStateEntities (req, setState) {
|
|
207
213
|
const keys = Object.keys(setState);
|
|
208
214
|
|
|
@@ -348,13 +354,13 @@ class Ai {
|
|
|
348
354
|
const rules = this.matcher.preprocessRule(intent);
|
|
349
355
|
const matcher = this._createIntentMatcher(rules, usedEntities);
|
|
350
356
|
|
|
351
|
-
return async (req) => {
|
|
357
|
+
return async (req, res) => {
|
|
352
358
|
if (!req.isTextOrIntent()) {
|
|
353
359
|
return false;
|
|
354
360
|
}
|
|
355
361
|
|
|
356
362
|
if (!req.intents) {
|
|
357
|
-
await this._loadIntents(req);
|
|
363
|
+
await this._loadIntents(req, res);
|
|
358
364
|
}
|
|
359
365
|
|
|
360
366
|
const winningIntent = matcher(req);
|
|
@@ -523,9 +529,10 @@ class Ai {
|
|
|
523
529
|
/**
|
|
524
530
|
*
|
|
525
531
|
* @param {Request} req
|
|
532
|
+
* @param {Responder} [res]
|
|
526
533
|
* @returns {Promise}
|
|
527
534
|
*/
|
|
528
|
-
async preloadAi (req) {
|
|
535
|
+
async preloadAi (req, res = null) {
|
|
529
536
|
if (req.supportsFeature(req.FEATURE_PHRASES)) {
|
|
530
537
|
const model = this._getModelForRequest(req, false);
|
|
531
538
|
|
|
@@ -534,7 +541,7 @@ class Ai {
|
|
|
534
541
|
.catch(() => {});
|
|
535
542
|
}
|
|
536
543
|
}
|
|
537
|
-
return this._preloadIntent(req);
|
|
544
|
+
return this._preloadIntent(req, res);
|
|
538
545
|
}
|
|
539
546
|
|
|
540
547
|
/**
|
|
@@ -552,12 +559,43 @@ class Ai {
|
|
|
552
559
|
return CustomEntityDetectionModel.getEmptyPhrasesObject();
|
|
553
560
|
}
|
|
554
561
|
|
|
555
|
-
|
|
562
|
+
/**
|
|
563
|
+
*
|
|
564
|
+
* @param {Request} req
|
|
565
|
+
* @param {Responder} res
|
|
566
|
+
* @param {Result} result
|
|
567
|
+
* @returns {void}
|
|
568
|
+
*/
|
|
569
|
+
_setResultToReqRes (req, res, result) {
|
|
570
|
+
const { text = null, intents, entities = [] } = result;
|
|
571
|
+
Object.assign(req, { intents, entities, _anonymizedText: text });
|
|
572
|
+
|
|
573
|
+
if (!res) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const entitiesObj = (entities || []).reduce((o, { entity, value }) => {
|
|
578
|
+
const list = o[entity] || [];
|
|
579
|
+
list.push(value);
|
|
580
|
+
return Object.assign(o, { [entity]: list });
|
|
581
|
+
}, {});
|
|
582
|
+
|
|
583
|
+
res.setData({
|
|
584
|
+
'@': entitiesObj
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
*
|
|
590
|
+
* @param {Request} req
|
|
591
|
+
* @param {Responder} [res]
|
|
592
|
+
* @returns {Promise}
|
|
593
|
+
*/
|
|
594
|
+
async _preloadIntent (req, res = null) {
|
|
556
595
|
const mockIntent = this._getMockIntent(req);
|
|
557
596
|
|
|
558
597
|
if (mockIntent) {
|
|
559
|
-
req
|
|
560
|
-
req.entities = mockIntent.entities;
|
|
598
|
+
this._setResultToReqRes(req, res, mockIntent);
|
|
561
599
|
return;
|
|
562
600
|
}
|
|
563
601
|
|
|
@@ -571,15 +609,15 @@ class Ai {
|
|
|
571
609
|
req.intents = [];
|
|
572
610
|
return;
|
|
573
611
|
}
|
|
574
|
-
await this._loadIntents(req, model);
|
|
612
|
+
await this._loadIntents(req, res, model);
|
|
575
613
|
} else {
|
|
576
614
|
req.intents = [];
|
|
577
615
|
}
|
|
578
616
|
}
|
|
579
617
|
|
|
580
|
-
async _loadIntents (req, model = null) {
|
|
581
|
-
const
|
|
582
|
-
|
|
618
|
+
async _loadIntents (req, res = null, model = null) {
|
|
619
|
+
const result = await this._queryModel(req, model);
|
|
620
|
+
this._setResultToReqRes(req, res, result);
|
|
583
621
|
}
|
|
584
622
|
|
|
585
623
|
async _queryModel (req, useModel = null) {
|
package/src/AiMatching.js
CHANGED
|
@@ -132,6 +132,12 @@ class AiMatching {
|
|
|
132
132
|
* @type {number}
|
|
133
133
|
*/
|
|
134
134
|
this.multiMatchGain = 1.2;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Score of a context entity within a conversation state
|
|
138
|
+
* (1 by default)
|
|
139
|
+
*/
|
|
140
|
+
this.stateEntityScore = 1;
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
get redundantHandicap () {
|
|
@@ -480,6 +486,10 @@ class AiMatching {
|
|
|
480
486
|
return winningIntent;
|
|
481
487
|
}
|
|
482
488
|
|
|
489
|
+
_getMultiMatchGain (entitiesScore, matchedCount, fromState = 0) {
|
|
490
|
+
return (this.multiMatchGain * entitiesScore) ** (matchedCount - fromState);
|
|
491
|
+
}
|
|
492
|
+
|
|
483
493
|
/**
|
|
484
494
|
*
|
|
485
495
|
* @private
|
|
@@ -505,7 +515,7 @@ class AiMatching {
|
|
|
505
515
|
}
|
|
506
516
|
|
|
507
517
|
const {
|
|
508
|
-
score: entitiesScore, handicap, matched, minScore
|
|
518
|
+
score: entitiesScore, handicap, matched, minScore, fromState
|
|
509
519
|
} = this
|
|
510
520
|
._entityMatching(
|
|
511
521
|
wantedEntities,
|
|
@@ -516,13 +526,20 @@ class AiMatching {
|
|
|
516
526
|
: (x) => x
|
|
517
527
|
);
|
|
518
528
|
|
|
529
|
+
// console.log({ entitiesScore, handicap, matched, minScore, requestIntent })
|
|
530
|
+
|
|
519
531
|
const allOptional = wantedEntities.every((e) => e.optional);
|
|
520
532
|
if (entitiesScore === 0 && !allOptional) {
|
|
521
533
|
return { score: 0, entities: [] };
|
|
522
534
|
}
|
|
523
535
|
|
|
524
|
-
const
|
|
525
|
-
|
|
536
|
+
const normalizedScore = Math.min(minScore + (handicap / 2), requestIntent.score);
|
|
537
|
+
const scoreWithHandicap = normalizedScore - handicap;
|
|
538
|
+
const multiMatchGain = this._getMultiMatchGain(entitiesScore, matched.length, fromState);
|
|
539
|
+
|
|
540
|
+
const score = scoreWithHandicap * multiMatchGain;
|
|
541
|
+
|
|
542
|
+
// console.log({ IMS: score, normalizedScore, scoreWithHandicap, multiMatchGain });
|
|
526
543
|
|
|
527
544
|
return {
|
|
528
545
|
score,
|
|
@@ -537,7 +554,7 @@ class AiMatching {
|
|
|
537
554
|
* @param {Entity[]} requestEntities
|
|
538
555
|
* @param {object} [requestState]
|
|
539
556
|
* @param {Function} [scoreFn]
|
|
540
|
-
* @returns {{score:
|
|
557
|
+
* @returns {{score:number,handicap:number, matched:Entity[],minScore:number,fromState:number}}
|
|
541
558
|
*/
|
|
542
559
|
_entityMatching (wantedEntities, requestEntities = [], requestState = {}, scoreFn = (x) => x) {
|
|
543
560
|
const occurences = new Map();
|
|
@@ -546,6 +563,7 @@ class AiMatching {
|
|
|
546
563
|
let handicap = 0;
|
|
547
564
|
let sum = 0;
|
|
548
565
|
let minScore = 1;
|
|
566
|
+
let fromState = 0;
|
|
549
567
|
|
|
550
568
|
for (const wanted of wantedEntities) {
|
|
551
569
|
const usedIndexes = occurences.has(wanted.entity)
|
|
@@ -579,9 +597,11 @@ class AiMatching {
|
|
|
579
597
|
requestEntity = {
|
|
580
598
|
value: requestState[`@${wanted.entity}`],
|
|
581
599
|
entity: wanted.entity,
|
|
582
|
-
score:
|
|
600
|
+
score: this.stateEntityScore
|
|
583
601
|
};
|
|
584
602
|
|
|
603
|
+
fromState += 1;
|
|
604
|
+
|
|
585
605
|
matching = this._entityIsMatching(
|
|
586
606
|
wanted.op,
|
|
587
607
|
wanted.compare,
|
|
@@ -596,7 +616,7 @@ class AiMatching {
|
|
|
596
616
|
|
|
597
617
|
if (!matching && !wanted.optional) {
|
|
598
618
|
return {
|
|
599
|
-
score: 0, handicap: 0, matched: [], minScore
|
|
619
|
+
score: 0, handicap: 0, matched: [], minScore, fromState
|
|
600
620
|
};
|
|
601
621
|
}
|
|
602
622
|
|
|
@@ -636,11 +656,15 @@ class AiMatching {
|
|
|
636
656
|
}
|
|
637
657
|
}
|
|
638
658
|
|
|
639
|
-
handicap
|
|
659
|
+
// console.log({ sum, handicap, rl: requestEntities.length, ml: matched.length });
|
|
660
|
+
|
|
661
|
+
// @todo - neni mozne, by doslo k negativnimu handicapu
|
|
662
|
+
handicap += (requestEntities.length + fromState - matched.length)
|
|
663
|
+
* this.redundantEntityHandicap;
|
|
640
664
|
const score = matched.length === 0 ? 0 : sum / matched.length;
|
|
641
665
|
|
|
642
666
|
return {
|
|
643
|
-
score, handicap, matched, minScore
|
|
667
|
+
score, handicap, matched, minScore, fromState
|
|
644
668
|
};
|
|
645
669
|
}
|
|
646
670
|
|
package/src/BotApp.js
CHANGED
|
@@ -248,7 +248,7 @@ class BotApp {
|
|
|
248
248
|
};
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
const sender = await this.createSender(senderId, pageId, message);
|
|
251
|
+
const sender = await this.createSender(senderId, pageId, message, secret, appId);
|
|
252
252
|
const res = await this._processor.processMessage(message, pageId, sender, { appId });
|
|
253
253
|
await this._processSenderResponses(sender, senderId, pageId, headers);
|
|
254
254
|
|
|
@@ -266,13 +266,15 @@ class BotApp {
|
|
|
266
266
|
* @param {string} pageId
|
|
267
267
|
* @param {object} [message]
|
|
268
268
|
* @param {string|Promise<string>} [secret]
|
|
269
|
+
* @param {string} appId
|
|
269
270
|
* @returns {Promise<BotAppSender>}
|
|
270
271
|
*/
|
|
271
272
|
async createSender (
|
|
272
273
|
senderId,
|
|
273
274
|
pageId,
|
|
274
275
|
message = defaultMsg(senderId, pageId),
|
|
275
|
-
secret = this._secret
|
|
276
|
+
secret = this._secret,
|
|
277
|
+
appId = this._appId
|
|
276
278
|
) {
|
|
277
279
|
const useSecret = await Promise.resolve(secret);
|
|
278
280
|
|
|
@@ -282,7 +284,7 @@ class BotApp {
|
|
|
282
284
|
...this._returnSenderOptions,
|
|
283
285
|
apiUrl: this._apiUrl,
|
|
284
286
|
pageId,
|
|
285
|
-
appId
|
|
287
|
+
appId,
|
|
286
288
|
secret: useSecret,
|
|
287
289
|
mid: setResponseToMid,
|
|
288
290
|
fetch: this._fetch,
|
package/src/Processor.js
CHANGED
package/src/Request.js
CHANGED
|
@@ -1227,7 +1227,6 @@ class Request {
|
|
|
1227
1227
|
// to match the local context intent
|
|
1228
1228
|
const localRegexToMatch = this._getLocalPathRegexp();
|
|
1229
1229
|
|
|
1230
|
-
const localEnhancement = (1 - Ai.ai.confidence) / 2;
|
|
1231
1230
|
for (const gi of this.globalIntents.values()) {
|
|
1232
1231
|
const pathMatches = localRegexToMatch && localRegexToMatch.exec(gi.action);
|
|
1233
1232
|
if (gi.local && !pathMatches) {
|
|
@@ -1235,7 +1234,9 @@ class Request {
|
|
|
1235
1234
|
}
|
|
1236
1235
|
const intent = gi.matcher(this, null, true);
|
|
1237
1236
|
if (intent !== null) {
|
|
1238
|
-
const sort = intent.score + (pathMatches
|
|
1237
|
+
const sort = intent.score + (pathMatches
|
|
1238
|
+
? Ai.ai.localEnhancement
|
|
1239
|
+
: 0);
|
|
1239
1240
|
// console.log(sort, wi.intent);
|
|
1240
1241
|
aiActions.push({
|
|
1241
1242
|
...gi,
|
package/src/utils/stateData.js
CHANGED
|
@@ -3,8 +3,19 @@
|
|
|
3
3
|
*/
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
|
+
/** @typedef {import('../Request')} Request */
|
|
7
|
+
/** @typedef {import('../Responder')} Responder */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {Request} req
|
|
12
|
+
* @param {Responder} res
|
|
13
|
+
* @param {object} configuration
|
|
14
|
+
* @returns {object}
|
|
15
|
+
*/
|
|
6
16
|
module.exports = function stateData (req, res = null, configuration = null) {
|
|
7
17
|
const c = configuration || req.configuration;
|
|
18
|
+
|
|
8
19
|
return {
|
|
9
20
|
...req.state,
|
|
10
21
|
...(res ? res.newState : {}),
|