Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit cb9d291

Browse files
feich-msboydc2014
andauthored
support multi trigger intents point to same lu file (#714)
* support multi trigger intents point to same lu file * optimize config structure * optimize config object parser * fix bug * fix minor typo Co-authored-by: Dong Lei <[email protected]>
1 parent 31488b4 commit cb9d291

File tree

4 files changed

+160
-35
lines changed

4 files changed

+160
-35
lines changed

packages/lu/src/parser/cross-train/crossTrainer.js

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,32 @@ const constructResoureTree = function (fileIdToLuResourceMap, triggerRules) {
9393
}
9494
}
9595

96-
const destLuFileToIntent = triggerRules[fileId]
97-
for (const destLuFile of Object.keys(destLuFileToIntent)) {
98-
if (destLuFile !== '' && !fileIdsFromInput.includes(destLuFile)) continue
99-
100-
const triggerIntentName = destLuFileToIntent[destLuFile]
101-
if (triggerIntentName !== '' && !intents.some(i => i.Name === triggerIntentName)) {
102-
throw (new exception(retCode.errorCode.INVALID_INPUT, `Sorry, trigger intent '${triggerIntentName}' is not found in lu file: ${fileId}`))
96+
const intentToDestLuFiles = triggerRules[fileId]
97+
for (const triggerIntent of Object.keys(intentToDestLuFiles)) {
98+
if (triggerIntent !== '' && !intents.some(i => i.Name === triggerIntent)) {
99+
throw (new exception(retCode.errorCode.INVALID_INPUT, `Sorry, trigger intent '${triggerIntent}' is not found in lu file: ${fileId}`))
103100
}
104101

105-
resource.children.push({
106-
target: destLuFile,
107-
intent: triggerIntentName
108-
})
102+
let destLuFiles = intentToDestLuFiles[triggerIntent]
103+
if (typeof destLuFiles === 'string') destLuFiles = [destLuFiles]
104+
105+
if (destLuFiles.length > 0) {
106+
destLuFiles.forEach(destLuFile => {
107+
if (destLuFile !== '' && !fileIdsFromInput.includes(destLuFile)) {
108+
throw (new exception(retCode.errorCode.INVALID_INPUT, `Sorry, lu file '${destLuFile}' is not found`))
109+
} else {
110+
resource.children.push({
111+
target: destLuFile,
112+
intent: triggerIntent
113+
})
114+
}
115+
})
116+
} else {
117+
resource.children.push({
118+
target: '',
119+
intent: triggerIntent
120+
})
121+
}
109122
}
110123

111124
resources.push(resource)
@@ -158,11 +171,16 @@ const mergeRootInterruptionToLeaves = function (rootResource, result, qnaFileToR
158171
const mergeBrothersInterruption = function (resource, result, intentName) {
159172
let children = resource.children
160173
for (const child of children) {
161-
let triggerIntent = child.intent
174+
const triggerIntent = child.intent
175+
const destLuFile = child.target
176+
let intentsWithSameTarget = []
177+
if (destLuFile !== '') intentsWithSameTarget = children.filter(c => c.target === destLuFile && c.intent !== '').map(x => x.intent)
178+
162179
const brotherSections = resource.content.Sections.filter(s => s.Name !== triggerIntent
163180
&& s.Name !== intentName
164181
&& (s.SectionType === LUSectionTypes.SIMPLEINTENTSECTION || s.SectionType === LUSectionTypes.NESTEDINTENTSECTION)
165-
&& children.some(brotherChild => brotherChild.intent === s.Name))
182+
&& children.some(brotherChild => brotherChild.intent === s.Name)
183+
&& !intentsWithSameTarget.some(intent => intent === s.Name))
166184

167185
let brotherUtterances = []
168186
brotherSections.forEach(s => {

packages/lu/src/utils/filehelper.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,18 @@ export function getConfigObject(configContent: any, intentName: string) {
239239
for (const triggerKey of Object.keys(triggers)) {
240240
const destLuFiles = triggers[triggerKey] instanceof Array ? triggers[triggerKey] : [triggers[triggerKey]]
241241
for (const destLuFile of destLuFiles) {
242-
const destLuFileFullPath = path.resolve(configFileDir, destLuFile)
242+
const destLuFileFullPath = destLuFile && destLuFile !== '' ? path.resolve(configFileDir, destLuFile) : destLuFile
243243
if (rootLuFileFullPath in finalLuConfigObj) {
244-
const finalDestLuFileToIntent = finalLuConfigObj[rootLuFileFullPath]
245-
finalDestLuFileToIntent[destLuFileFullPath] = triggerKey
244+
const finalIntentToDestLuFiles = finalLuConfigObj[rootLuFileFullPath]
245+
if (finalIntentToDestLuFiles[triggerKey]) {
246+
finalIntentToDestLuFiles[triggerKey].push(destLuFileFullPath)
247+
} else {
248+
finalIntentToDestLuFiles[triggerKey] = [destLuFileFullPath]
249+
}
246250
} else {
247-
let finalDestLuFileToIntent = Object.create(null)
248-
finalDestLuFileToIntent[destLuFileFullPath] = triggerKey
249-
finalLuConfigObj[rootLuFileFullPath] = finalDestLuFileToIntent
251+
let finalIntentToDestLuFiles = Object.create(null)
252+
finalIntentToDestLuFiles[triggerKey] = [destLuFileFullPath]
253+
finalLuConfigObj[rootLuFileFullPath] = finalIntentToDestLuFiles
250254
}
251255
}
252256
}

packages/lu/test/parser/cross-train/crossTrainer.test.js

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,15 @@ describe('luis:cross training tests among lu and qna contents', () => {
170170
],
171171
triggerRules: {
172172
'main.lu': {
173-
'dia1.lu': 'dia1_trigger',
174-
'dia2.lu': 'dia2_trigger'
173+
'dia1_trigger': 'dia1.lu',
174+
'dia2_trigger': 'dia2.lu'
175175
},
176176
'dia2.lu': {
177-
'dia3.lu': 'dia3_trigger',
178-
'dia4.lu': 'dia4_trigger'
177+
'dia3_trigger': 'dia3.lu',
178+
'dia4_trigger': 'dia4.lu'
179179
},
180180
'main.fr-fr.lu': {
181-
'dia1.fr-fr.lu': 'dia1_trigger'
181+
'dia1_trigger': 'dia1.fr-fr.lu'
182182
}
183183
},
184184
intentName: '_Interruption',
@@ -284,8 +284,8 @@ describe('luis:cross training tests among lu and qna contents', () => {
284284
],
285285
triggerRules: {
286286
'./main/main.lu': {
287-
'./dia1/dia1.lu': 'dia1_trigger',
288-
'./dia2/dia2.lu': 'dia2_trigger'
287+
'dia1_trigger': './dia1/dia1.lu',
288+
'dia2_trigger': './dia2/dia2.lu'
289289
}
290290
},
291291
intentName: '_Interruption',
@@ -339,9 +339,8 @@ describe('luis:cross training tests among lu and qna contents', () => {
339339
],
340340
triggerRules: {
341341
'./main/main.lu': {
342-
'./dia1/dia1.lu': 'dia1_trigger',
343-
'./dia2/dia2.lu': 'dia1_trigger',
344-
'./dia3/dia3.lu': 'dia2_trigger'
342+
'dia1_trigger': ['./dia1/dia1.lu', './dia2/dia2.lu'],
343+
'dia2_trigger': './dia3/dia3.lu'
345344
}
346345
},
347346
intentName: '_Interruption',
@@ -398,8 +397,8 @@ describe('luis:cross training tests among lu and qna contents', () => {
398397
],
399398
triggerRules: {
400399
'./main/main.lu': {
401-
'./dia1/dia1.lu': 'dia1_trigger',
402-
'./dia2/dia2.lu': 'dia2_trigger'
400+
'dia1_trigger': './dia1/dia1.lu',
401+
'dia2_trigger': './dia2/dia2.lu'
403402
}
404403
},
405404
intentName: '_Interruption',
@@ -460,10 +459,10 @@ describe('luis:cross training tests among lu and qna contents', () => {
460459
],
461460
triggerRules: {
462461
'./main/main.lu': {
463-
'./dia1/dia1.lu': 'dia1_trigger',
464-
'./dia2/dia2.lu': 'dia2_trigger',
465-
'': 'dia3_trigger',
466-
'./dia3/dia3.lu': ''
462+
'dia1_trigger': './dia1/dia1.lu',
463+
'dia2_trigger': './dia2/dia2.lu',
464+
'dia3_trigger': '',
465+
'': './dia3/dia3.lu'
467466
}
468467
},
469468
intentName: '_Interruption',
@@ -482,4 +481,64 @@ describe('luis:cross training tests among lu and qna contents', () => {
482481
assert.equal(luResult.get('./dia3/dia3.lu').Sections[1].Name, '_Interruption')
483482
assert.equal(luResult.get('./dia3/dia3.lu').Sections[1].Body, `- I want to travel to Seattle${NEWLINE}- book a hotel for me${NEWLINE}- cancel`)
484483
})
484+
485+
it('luis:cross training can get expected result when multi trigger intents point to same lu file', () => {
486+
let luContentArray = []
487+
488+
luContentArray.push({
489+
content:
490+
`# dia1_trigger
491+
- I want to travel to Seattle
492+
493+
# dia2_trigger
494+
- book a hotel for me
495+
496+
# dia3_trigger
497+
- cancel`,
498+
id: './main/main.lu'}
499+
)
500+
501+
luContentArray.push({
502+
content:
503+
`# bookTicket
504+
- book a flight for me
505+
- book a train ticket for me
506+
507+
# hotelLevel
508+
- I prefer 4 stars hotel`,
509+
id: './dia1/dia1.lu'}
510+
)
511+
512+
luContentArray.push({
513+
content:
514+
`# cancelTask
515+
- cancel that task`,
516+
id: './dia2/dia2.lu'}
517+
)
518+
519+
let crossTrainConfig = {
520+
rootIds: [
521+
'./main/main.lu'
522+
],
523+
triggerRules: {
524+
'./main/main.lu': {
525+
'dia1_trigger': './dia1/dia1.lu',
526+
'dia2_trigger': './dia1/dia1.lu',
527+
'dia3_trigger': './dia2/dia2.lu',
528+
'': './dia2/dia2.lu'
529+
}
530+
},
531+
intentName: '_Interruption',
532+
verbose: true
533+
}
534+
535+
const trainedResult = crossTrainer.crossTrain(luContentArray, [], crossTrainConfig)
536+
const luResult = trainedResult.luResult
537+
538+
assert.equal(luResult.get('./dia1/dia1.lu').Sections[2].Name, '_Interruption')
539+
assert.equal(luResult.get('./dia1/dia1.lu').Sections[2].Body, `- cancel`)
540+
541+
assert.equal(luResult.get('./dia2/dia2.lu').Sections[1].Name, '_Interruption')
542+
assert.equal(luResult.get('./dia2/dia2.lu').Sections[1].Body, `- I want to travel to Seattle${NEWLINE}- book a hotel for me`)
543+
})
485544
})

packages/lu/test/utils/filehelper.test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {readTextFile} from './../../src/utils/textfilereader'
22
const expect = require('chai').expect;
3+
const assert = require('chai').assert
34
const fileHelper = require('./../../src/utils/filehelper')
45
const luObject = require('./../../src/parser/lu/lu')
56
const luOptions = require('./../../src/parser/lu/luOptions')
@@ -28,4 +29,47 @@ describe('utils/filehelper test', () => {
2829
expected.push(new luObject(content, new luOptions('stdin')))
2930
expect(luObjArray).to.deep.equal(expected)
3031
})
32+
33+
it('File helper correctly build cross train config object', function () {
34+
const configContent = {
35+
"./main/main.lu": {
36+
"rootDialog": true,
37+
"triggers": {
38+
"dia1_trigger": ["./dia1/dia1.lu", "./dia2/dia2.lu"]
39+
}
40+
},
41+
"./dia2/dia2.lu": {
42+
"triggers": {
43+
"dia3_trigger": "",
44+
"": "./dia4/dia4.lu"
45+
}
46+
},
47+
"./main/main.fr-fr.lu": {
48+
"rootDialog": true,
49+
"triggers": {
50+
"dia1_trigger": "./dia1/dia1.fr-fr.lu"
51+
}
52+
}
53+
}
54+
55+
let configObject = fileHelper.getConfigObject({ id: path.join(__dirname, 'config.json'), content: JSON.stringify(configContent) }, '_Interruption')
56+
assert.equal(configObject.rootIds[0].includes('main.lu'), true)
57+
assert.equal(configObject.rootIds[1].includes('main.fr-fr.lu'), true)
58+
59+
const triggerRuleKeys = [...Object.keys(configObject.triggerRules)]
60+
assert.equal(triggerRuleKeys[0].includes('main.lu'), true)
61+
assert.equal(triggerRuleKeys[1].includes('dia2.lu'), true)
62+
assert.equal(triggerRuleKeys[2].includes('main.fr-fr.lu'), true)
63+
64+
const triggerRuleValues = [...Object.values(configObject.triggerRules)]
65+
assert.equal(triggerRuleValues[0]['dia1_trigger'][0].includes('dia1.lu'), true)
66+
assert.equal(triggerRuleValues[0]['dia1_trigger'][1].includes('dia2.lu'), true)
67+
assert.equal(triggerRuleValues[1]['dia3_trigger'][0], '')
68+
assert.equal(triggerRuleValues[1][''][0].includes('dia4.lu'), true)
69+
assert.equal(triggerRuleValues[2]['dia1_trigger'][0].includes('dia1.fr-fr.lu'), true)
70+
71+
assert.equal(configObject.intentName, '_Interruption')
72+
73+
assert.equal(configObject.verbose, true)
74+
})
3175
})

0 commit comments

Comments
 (0)