wingbot 3.53.3 → 3.53.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/AiMatching.js +88 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.53.3",
3
+ "version": "3.53.5",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/AiMatching.js CHANGED
@@ -23,6 +23,16 @@ const FULL_EMOJI_REGEX = /^#((?:[\u2600-\u27bf].?|(?:\ud83c[\udde6-\uddff]){2}|[
23
23
  const HAS_CLOSING_HASH = /^#(.+)#$/;
24
24
  const ENTITY_REGEX = /^@([^=><!?]+)(\?)?([!=><]{1,2})?([^=><!]+)?$/i;
25
25
 
26
+ /**
27
+ * @typedef {object} EntityMatchingResult
28
+ * @prop {number} score
29
+ * @prop {number} handicap
30
+ * @prop {number} fromState
31
+ * @prop {number} minScore
32
+ * @prop {number} metl
33
+ * @prop {Entity[]} matched
34
+ */
35
+
26
36
  /**
27
37
  * RegExp to test a string for a ISO 8601 Date spec
28
38
  * YYYY
@@ -449,6 +459,7 @@ class AiMatching {
449
459
 
450
460
  const noIntentHandicap = req.intents.length === 0 ? 0 : this.redundantIntentHandicap;
451
461
  const regexpScore = this._matchRegexp(req, regexps, noIntentHandicap);
462
+ const textLength = req.text().trim().length;
452
463
 
453
464
  if (regexpScore !== 0 || (intents.length === 0 && regexps.length === 0)) {
454
465
 
@@ -477,8 +488,11 @@ class AiMatching {
477
488
  useState = stateData(req);
478
489
  }
479
490
 
480
- const { score, handicap, matched } = this
491
+ const {
492
+ score, handicap, matched, metl
493
+ } = this
481
494
  ._entityMatching(
495
+ textLength,
482
496
  entities,
483
497
  reqEntities,
484
498
  useState
@@ -499,33 +513,25 @@ class AiMatching {
499
513
  ? score - noIntentHandicap
500
514
  : (regexpScore + score) / 2;
501
515
 
502
- const matchedEntitiesTextLength = matched.reduce((tot, entity) => (
503
- typeof entity.end === 'number' && typeof entity.start === 'number' && tot !== null
504
- ? (tot + (entity.end - entity.start))
505
- : null
506
- ), 0);
507
-
508
516
  let finalScore = (baseScore - handicap)
509
517
  * (this.multiMatchGain ** countOfAdditionalItems);
510
518
 
511
- const textLength = req.text().length;
512
-
513
- if (matchedEntitiesTextLength && textLength) {
519
+ if (metl && textLength) {
514
520
  const remainingScore = Math.max(0, Math.min(1, finalScore) - (
515
521
  this._ai.confidence + this.redundantEntityHandicap
516
522
  ));
517
523
 
518
- const remainingTextLen = (textLength - matchedEntitiesTextLength);
524
+ const remainingTextLen = (textLength - metl);
519
525
  const minus = (remainingTextLen / textLength) * remainingScore;
520
526
 
521
- // eslint-disable-next-line no-console,max-len,object-curly-newline
522
- // console.log({ minus, matchedEntitiesTextLength, textLength, remainingScore })
527
+ // eslint-disable-next-line max-len,object-curly-newline
528
+ // console.log({ minus, metl, textLength, remainingScore })
523
529
 
524
530
  finalScore -= minus;
525
531
  }
526
532
 
527
- // eslint-disable-next-line no-console,max-len,object-curly-newline
528
- // console.log({ countOfAdditionalItems, multiMatch: this.multiMatchGain ** countOfAdditionalItems, handicap, finalScore, rule, baseScore, score, allOptional, entities, reqEntities, matchedEntitiesTextLength, countOfAdditionalItems });
533
+ // eslint-disable-next-line max-len,object-curly-newline
534
+ // console.log({ countOfAdditionalItems, multiMatch: this.multiMatchGain ** countOfAdditionalItems, handicap, useHandicap, finalScore, rule, baseScore, score, allOptional, entities, reqEntities, matchedEntitiesTextLength });
529
535
 
530
536
  if (finalScore <= 0) {
531
537
  return null;
@@ -549,7 +555,14 @@ class AiMatching {
549
555
  let max = total;
550
556
  for (const requestIntent of req.intents) {
551
557
  const { score, entities: matchedEntities } = this
552
- ._intentMatchingScore(wanted, requestIntent, entities, req, stateless);
558
+ ._intentMatchingScore(
559
+ textLength,
560
+ wanted,
561
+ requestIntent,
562
+ entities,
563
+ req,
564
+ stateless
565
+ );
553
566
 
554
567
  if (score > max) {
555
568
  max = score;
@@ -576,6 +589,7 @@ class AiMatching {
576
589
  /**
577
590
  *
578
591
  * @private
592
+ * @param {number} textLength
579
593
  * @param {string} wantedIntent
580
594
  * @param {Intent} requestIntent
581
595
  * @param {EntityExpression[]} wantedEntities
@@ -583,7 +597,14 @@ class AiMatching {
583
597
  * @param {boolean} stateless
584
598
  * @returns {{score:number,entities:Entity[]}}
585
599
  */
586
- _intentMatchingScore (wantedIntent, requestIntent, wantedEntities, req, stateless = false) {
600
+ _intentMatchingScore (
601
+ textLength,
602
+ wantedIntent,
603
+ requestIntent,
604
+ wantedEntities,
605
+ req,
606
+ stateless = false
607
+ ) {
587
608
  if (wantedIntent !== requestIntent.intent) {
588
609
  return { score: 0, entities: [] };
589
610
  }
@@ -601,15 +622,17 @@ class AiMatching {
601
622
  score: entitiesScore, handicap, matched, minScore, fromState
602
623
  } = this
603
624
  ._entityMatching(
625
+ textLength,
604
626
  wantedEntities,
605
627
  useEntities,
606
628
  stateless ? {} : req.state,
607
629
  requestIntent.entities
608
630
  ? (x) => Math.atan((x - 0.76) * 40) / Math.atan((1 - 0.76) * 40)
609
- : (x) => x
631
+ : (x) => x,
632
+ req.entities
610
633
  );
611
634
 
612
- // eslint-disable-next-line no-console,max-len,object-curly-newline
635
+ // eslint-disable-next-line max-len,object-curly-newline
613
636
  // console.log({ wantedEntities, entitiesScore, handicap, matched, minScore, requestIntent });
614
637
 
615
638
  const allOptional = wantedEntities.every((e) => e.optional
@@ -624,7 +647,7 @@ class AiMatching {
624
647
 
625
648
  const score = Math.round((scoreWithHandicap * multiMatchGain) * 10000) / 10000;
626
649
 
627
- // eslint-disable-next-line no-console,max-len,object-curly-newline
650
+ // eslint-disable-next-line max-len,object-curly-newline
628
651
  // console.log({ IMS: score, normalizedScore, scoreWithHandicap, multiMatchGain, wantedEntities });
629
652
 
630
653
  return {
@@ -636,13 +659,23 @@ class AiMatching {
636
659
  /**
637
660
  *
638
661
  * @private
662
+ * @param {number} textLen
639
663
  * @param {EntityExpression[]} wantedEntities
640
664
  * @param {Entity[]} requestEntities
641
665
  * @param {object} [requestState]
642
666
  * @param {Function} [scoreFn]
643
- * @returns {{score:number,handicap:number, matched:Entity[],minScore:number,fromState:number}}
667
+ * @param {Entity[]} allEntities
668
+ *
669
+ * @returns {EntityMatchingResult}
644
670
  */
645
- _entityMatching (wantedEntities, requestEntities = [], requestState = {}, scoreFn = (x) => x) {
671
+ _entityMatching (
672
+ textLen,
673
+ wantedEntities,
674
+ requestEntities = [],
675
+ requestState = {},
676
+ scoreFn = (x) => x,
677
+ allEntities = requestEntities
678
+ ) {
646
679
  const occurences = new Map();
647
680
 
648
681
  const matched = [];
@@ -650,6 +683,7 @@ class AiMatching {
650
683
  let sum = 0;
651
684
  let minScore = 1;
652
685
  let fromState = 0;
686
+ let metl = 0;
653
687
 
654
688
  for (const wanted of wantedEntities) {
655
689
  const usedIndexes = occurences.has(wanted.entity)
@@ -702,7 +736,7 @@ class AiMatching {
702
736
 
703
737
  if (!matching && (!wanted.optional || entityExists)) {
704
738
  return {
705
- score: 0, handicap: 0, matched: [], minScore, fromState
739
+ score: 0, handicap: 0, matched: [], minScore, fromState, metl
706
740
  };
707
741
  }
708
742
 
@@ -728,6 +762,10 @@ class AiMatching {
728
762
  }
729
763
 
730
764
  if (requestEntity) {
765
+ if (typeof requestEntity.end === 'number' && typeof requestEntity.start === 'number') {
766
+ metl += requestEntity.end - requestEntity.start;
767
+ }
768
+
731
769
  matched.push(requestEntity);
732
770
  sum += scoreFn(requestEntity.score);
733
771
  if (index !== -1) {
@@ -744,16 +782,37 @@ class AiMatching {
744
782
  }
745
783
  }
746
784
 
747
- // eslint-disable-next-line no-console,max-len
748
- // console.log({ wantedEntities, sum, handicap, rl: requestEntities.length, ml: matched.length });
785
+ const withCoveringEntity = textLen && textLen <= metl;
786
+
787
+ // eslint-disable-next-line max-len
788
+ // console.log({ metl, withCoveringEntity, wantedEntities, sum, handicap, rl: requestEntities.length, ml: matched.length });
789
+
790
+ if (withCoveringEntity) {
791
+ handicap -= this.redundantEntityHandicap;
792
+ } else {
793
+ const otherEntitiesTextLen = allEntities
794
+ .filter((re) => !matched.some((e) => e.entity === re.entity))
795
+ .reduce((tot, entity) => (
796
+ typeof entity.end === 'number' && typeof entity.start === 'number'
797
+ ? (tot + (entity.end - entity.start))
798
+ : 0
799
+ ), 0);
800
+
801
+ const coveringHandicap = textLen && otherEntitiesTextLen >= textLen
802
+ ? 1
803
+ : 0;
749
804
 
750
- // @todo - neni mozne, by doslo k negativnimu handicapu
751
- handicap += (requestEntities.length + fromState - matched.length)
752
- * this.redundantEntityHandicap;
805
+ handicap += (requestEntities.length + fromState - matched.length + coveringHandicap)
806
+ * this.redundantEntityHandicap;
807
+
808
+ // eslint-disable-next-line max-len
809
+ // console.log({ requestEntities, matched, handicap, coveringHandicap, otherEntitiesTextLen });
810
+
811
+ }
753
812
  const score = matched.length === 0 ? 0 : sum / matched.length;
754
813
 
755
814
  return {
756
- score, handicap, matched, minScore, fromState
815
+ score, handicap, matched, minScore, fromState, metl
757
816
  };
758
817
  }
759
818