@botonic/plugin-flow-builder 0.26.2-alpha.0 → 0.27.0-alpha.0
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/lib/cjs/action/index.js +38 -18
- package/lib/cjs/action/index.js.map +1 -1
- package/lib/cjs/action/knowledge-bases.js +14 -4
- package/lib/cjs/action/knowledge-bases.js.map +1 -1
- package/lib/cjs/api.d.ts +2 -4
- package/lib/cjs/api.js +7 -32
- package/lib/cjs/api.js.map +1 -1
- package/lib/cjs/constants.d.ts +1 -1
- package/lib/cjs/constants.js +2 -2
- package/lib/cjs/constants.js.map +1 -1
- package/lib/cjs/content-fields/flow-handoff.js +7 -19
- package/lib/cjs/content-fields/flow-handoff.js.map +1 -1
- package/lib/cjs/content-fields/index.d.ts +1 -0
- package/lib/cjs/content-fields/index.js +3 -1
- package/lib/cjs/content-fields/index.js.map +1 -1
- package/lib/cjs/functions/conditional-queue-status.d.ts +7 -1
- package/lib/cjs/functions/conditional-queue-status.js +34 -12
- package/lib/cjs/functions/conditional-queue-status.js.map +1 -1
- package/lib/cjs/index.d.ts +6 -3
- package/lib/cjs/index.js +22 -13
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/tracking.d.ts +18 -14
- package/lib/cjs/tracking.js +27 -20
- package/lib/cjs/tracking.js.map +1 -1
- package/lib/cjs/types.d.ts +14 -1
- package/lib/cjs/types.js.map +1 -1
- package/lib/cjs/user-input/index.d.ts +2 -1
- package/lib/cjs/user-input/index.js +9 -3
- package/lib/cjs/user-input/index.js.map +1 -1
- package/lib/cjs/user-input/intent.js +12 -8
- package/lib/cjs/user-input/intent.js.map +1 -1
- package/lib/cjs/user-input/keyword.d.ts +21 -1
- package/lib/cjs/user-input/keyword.js +68 -13
- package/lib/cjs/user-input/keyword.js.map +1 -1
- package/lib/cjs/user-input/smart-intent.d.ts +18 -1
- package/lib/cjs/user-input/smart-intent.js +46 -28
- package/lib/cjs/user-input/smart-intent.js.map +1 -1
- package/lib/esm/action/index.js +39 -19
- package/lib/esm/action/index.js.map +1 -1
- package/lib/esm/action/knowledge-bases.js +15 -5
- package/lib/esm/action/knowledge-bases.js.map +1 -1
- package/lib/esm/api.d.ts +2 -4
- package/lib/esm/api.js +8 -33
- package/lib/esm/api.js.map +1 -1
- package/lib/esm/constants.d.ts +1 -1
- package/lib/esm/constants.js +1 -1
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/content-fields/flow-handoff.js +7 -19
- package/lib/esm/content-fields/flow-handoff.js.map +1 -1
- package/lib/esm/content-fields/index.d.ts +1 -0
- package/lib/esm/content-fields/index.js +1 -0
- package/lib/esm/content-fields/index.js.map +1 -1
- package/lib/esm/functions/conditional-queue-status.d.ts +7 -1
- package/lib/esm/functions/conditional-queue-status.js +32 -11
- package/lib/esm/functions/conditional-queue-status.js.map +1 -1
- package/lib/esm/index.d.ts +6 -3
- package/lib/esm/index.js +23 -14
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/tracking.d.ts +18 -14
- package/lib/esm/tracking.js +25 -19
- package/lib/esm/tracking.js.map +1 -1
- package/lib/esm/types.d.ts +14 -1
- package/lib/esm/types.js.map +1 -1
- package/lib/esm/user-input/index.d.ts +2 -1
- package/lib/esm/user-input/index.js +11 -5
- package/lib/esm/user-input/index.js.map +1 -1
- package/lib/esm/user-input/intent.js +13 -9
- package/lib/esm/user-input/intent.js.map +1 -1
- package/lib/esm/user-input/keyword.d.ts +21 -1
- package/lib/esm/user-input/keyword.js +67 -12
- package/lib/esm/user-input/keyword.js.map +1 -1
- package/lib/esm/user-input/smart-intent.d.ts +18 -1
- package/lib/esm/user-input/smart-intent.js +44 -26
- package/lib/esm/user-input/smart-intent.js.map +1 -1
- package/package.json +2 -2
- package/src/action/index.tsx +58 -24
- package/src/action/knowledge-bases.ts +16 -5
- package/src/api.ts +11 -57
- package/src/constants.ts +1 -1
- package/src/content-fields/flow-handoff.tsx +8 -28
- package/src/content-fields/index.ts +1 -0
- package/src/functions/conditional-queue-status.ts +36 -13
- package/src/index.ts +39 -19
- package/src/tracking.ts +25 -14
- package/src/types.ts +13 -1
- package/src/user-input/index.ts +13 -7
- package/src/user-input/intent.ts +17 -10
- package/src/user-input/keyword.ts +93 -14
- package/src/user-input/smart-intent.ts +57 -29
|
@@ -1,22 +1,101 @@
|
|
|
1
1
|
import { ActionRequest } from '@botonic/react'
|
|
2
2
|
|
|
3
3
|
import { FlowBuilderApi } from '../api'
|
|
4
|
+
import { REG_EXP_PATTERN } from '../constants'
|
|
4
5
|
import { HtKeywordNode } from '../content-fields/hubtype-fields'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
cmsApi: FlowBuilderApi
|
|
9
|
-
locale: string
|
|
10
|
-
request: ActionRequest
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
import { EventAction, trackEvent } from '../tracking'
|
|
7
|
+
|
|
8
|
+
interface KeywordProps {
|
|
9
|
+
cmsApi: FlowBuilderApi
|
|
10
|
+
locale: string
|
|
11
|
+
request: ActionRequest
|
|
12
|
+
}
|
|
13
|
+
export class KeywordMatcher {
|
|
14
|
+
public cmsApi: FlowBuilderApi
|
|
15
|
+
public locale: string
|
|
16
|
+
public request: ActionRequest
|
|
17
|
+
public isRegExp: boolean
|
|
18
|
+
public matchedKeyword?: string
|
|
19
|
+
public keywordNodeId?: string
|
|
20
|
+
|
|
21
|
+
constructor({ cmsApi, locale, request }: KeywordProps) {
|
|
22
|
+
this.cmsApi = cmsApi
|
|
23
|
+
this.locale = locale
|
|
24
|
+
this.request = request
|
|
25
|
+
this.isRegExp = false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getNodeByInput(userInput: string): Promise<HtKeywordNode | undefined> {
|
|
29
|
+
const keywordNodes = this.cmsApi.getKeywordNodes()
|
|
30
|
+
const keywordNode = this.getNodeByKeyword(userInput, keywordNodes)
|
|
31
|
+
if (!keywordNode) {
|
|
32
|
+
return undefined
|
|
33
|
+
}
|
|
34
|
+
this.trackKeywordEvent()
|
|
35
|
+
return keywordNode
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private getNodeByKeyword(
|
|
39
|
+
userInput: string,
|
|
40
|
+
keywordNodes: HtKeywordNode[]
|
|
41
|
+
): HtKeywordNode | undefined {
|
|
42
|
+
const matchedKeywordNodes = keywordNodes.filter(node =>
|
|
43
|
+
this.matchKeywords(userInput, node)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if (matchedKeywordNodes.length > 0 && matchedKeywordNodes[0].target) {
|
|
47
|
+
return matchedKeywordNodes[0]
|
|
48
|
+
}
|
|
49
|
+
|
|
15
50
|
return undefined
|
|
16
51
|
}
|
|
17
|
-
|
|
18
|
-
|
|
52
|
+
|
|
53
|
+
private matchKeywords(userInput: string, node: HtKeywordNode): boolean {
|
|
54
|
+
const result = node.content.keywords.find(keywords => {
|
|
55
|
+
if (keywords.locale === this.locale) {
|
|
56
|
+
this.keywordNodeId = node.id
|
|
57
|
+
return this.inputMatchesAnyKeyword(userInput, keywords.values)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return false
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return Boolean(result)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private inputMatchesAnyKeyword(
|
|
67
|
+
userInput: string,
|
|
68
|
+
keywords: string[]
|
|
69
|
+
): boolean {
|
|
70
|
+
return keywords.some(keyword => {
|
|
71
|
+
const regExpMatchArray = keyword.match(REG_EXP_PATTERN)
|
|
72
|
+
|
|
73
|
+
if (regExpMatchArray) {
|
|
74
|
+
const keywordAsRegExp = this.resolveKeywordAsRegExp(regExpMatchArray)
|
|
75
|
+
const match = userInput.match(keywordAsRegExp)
|
|
76
|
+
this.isRegExp = true
|
|
77
|
+
this.matchedKeyword = match ? match[0] : undefined
|
|
78
|
+
} else {
|
|
79
|
+
this.isRegExp = false
|
|
80
|
+
this.matchedKeyword = userInput.includes(keyword) ? keyword : undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return this.matchedKeyword !== undefined
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private resolveKeywordAsRegExp(regExpMatchArray: RegExpMatchArray): RegExp {
|
|
88
|
+
const [, pattern, flags] = regExpMatchArray
|
|
89
|
+
return new RegExp(pattern, flags)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private async trackKeywordEvent() {
|
|
93
|
+
const eventArgs = {
|
|
94
|
+
nluKeywordId: this.keywordNodeId,
|
|
95
|
+
nluKeywordName: this.matchedKeyword,
|
|
96
|
+
nluKeywordIsRegex: this.isRegExp,
|
|
97
|
+
nluKeywordMessageId: this.request.input.message_id,
|
|
98
|
+
}
|
|
99
|
+
await trackEvent(this.request, EventAction.keyword, eventArgs)
|
|
19
100
|
}
|
|
20
|
-
await trackEvent(request, EventName.botKeywordsModel, eventArgs)
|
|
21
|
-
return keywordNode
|
|
22
101
|
}
|
|
@@ -3,44 +3,72 @@ import axios from 'axios'
|
|
|
3
3
|
|
|
4
4
|
import { FlowBuilderApi } from '../api'
|
|
5
5
|
import { HtSmartIntentNode } from '../content-fields/hubtype-fields/smart-intent'
|
|
6
|
+
import { EventAction, trackEvent } from '../tracking'
|
|
7
|
+
import { SmartIntentResponse } from '../types'
|
|
6
8
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
export interface SmartIntentsInferenceParams {
|
|
10
|
+
bot_id: string
|
|
11
|
+
text: string
|
|
12
|
+
num_smart_intents_to_use?: number
|
|
13
|
+
use_latest: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SmartIntentsInferenceConfig {
|
|
17
|
+
useLatest: boolean
|
|
18
|
+
numSmartIntentsToUse?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class SmartIntentsApi {
|
|
22
|
+
constructor(
|
|
23
|
+
public cmsApi: FlowBuilderApi,
|
|
24
|
+
public currentRequest: ActionRequest,
|
|
25
|
+
public smartIntentsConfig: SmartIntentsInferenceConfig
|
|
26
|
+
) {}
|
|
27
|
+
|
|
28
|
+
async getNodeByInput(): Promise<HtSmartIntentNode | undefined> {
|
|
29
|
+
if (!this.currentRequest.input.data) return undefined
|
|
30
|
+
const smartIntentNodes = this.cmsApi.getSmartIntentNodes()
|
|
31
|
+
if (!smartIntentNodes.length) return undefined
|
|
32
|
+
|
|
33
|
+
const params = {
|
|
34
|
+
bot_id: this.currentRequest.session.bot.id,
|
|
35
|
+
text: this.currentRequest.input.data,
|
|
36
|
+
num_smart_intents_to_use: this.smartIntentsConfig.numSmartIntentsToUse,
|
|
37
|
+
use_latest: this.smartIntentsConfig.useLatest,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const response = await this.getInference(params)
|
|
42
|
+
const smartIntentNode = smartIntentNodes.find(
|
|
43
|
+
smartIntentNode =>
|
|
44
|
+
smartIntentNode.content.title === response.data.smart_intent_title
|
|
45
|
+
)
|
|
46
|
+
if (smartIntentNode) {
|
|
47
|
+
trackEvent(this.currentRequest, EventAction.intentSmart, {
|
|
48
|
+
nluIntentSmartTitle: response.data.smart_intent_title,
|
|
49
|
+
nluIntentSmartNumUsed: response.data.smart_intents_used,
|
|
50
|
+
nluIntentSmartMessageId: this.currentRequest.input.message_id,
|
|
51
|
+
})
|
|
52
|
+
return smartIntentNode
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
console.error(e)
|
|
56
|
+
}
|
|
13
57
|
return undefined
|
|
14
58
|
}
|
|
15
59
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
intentsInferenceParams.push({
|
|
23
|
-
name: 'Other',
|
|
24
|
-
definition: 'The text does not belong to any other intent.',
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const response = await axios({
|
|
60
|
+
private async getInference(
|
|
61
|
+
inferenceParams: SmartIntentsInferenceParams
|
|
62
|
+
): Promise<SmartIntentResponse> {
|
|
63
|
+
return await axios({
|
|
29
64
|
method: 'POST',
|
|
30
|
-
url: `${process.env.HUBTYPE_API_URL}/external/
|
|
65
|
+
url: `${process.env.HUBTYPE_API_URL}/external/v2/ai/smart_intents/inference/`,
|
|
31
66
|
headers: {
|
|
32
|
-
Authorization: `Bearer ${
|
|
67
|
+
Authorization: `Bearer ${this.currentRequest.session._access_token}`,
|
|
33
68
|
'Content-Type': 'application/json',
|
|
34
69
|
},
|
|
35
|
-
data:
|
|
70
|
+
data: inferenceParams,
|
|
36
71
|
timeout: 10000,
|
|
37
72
|
})
|
|
38
|
-
return smartIntentNodes.find(
|
|
39
|
-
smartIntentNode =>
|
|
40
|
-
smartIntentNode.content.title === response.data.intent_name
|
|
41
|
-
)
|
|
42
|
-
} catch (e) {
|
|
43
|
-
console.error(e)
|
|
44
|
-
return undefined
|
|
45
73
|
}
|
|
46
74
|
}
|