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

Commit c0be653

Browse files
Shuai Wangmunozemilio
andauthored
fix luis-cross train does not find imported files with locale (#1209)
* fix import file with locale * simplify test * change folder structures * remove only * add cross train config * fix spelling * modify test * change naming * fix readme * fix typo Co-authored-by: Emilio Munoz <[email protected]>
1 parent 83314e2 commit c0be653

File tree

15 files changed

+31170
-9
lines changed

15 files changed

+31170
-9
lines changed

packages/cli/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,8 @@ OPTIONS
891891
--[no-]intra-dialog Only do intra dialog cross train
892892
893893
--log Writes out log messages to console
894+
895+
--exclude Excludes given folders under the input directory, for example, --exclude bin,obj,lib, this will ignore the /bin, /obj, /lib folders under the input path
894896
```
895897

896898
_See code: [@microsoft/bf-luis-cli](https://github.com/microsoft/botframework-cli/tree/master/packages/luis/src/commands/luis/cross-train.ts)_

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,23 @@ module.exports = {
1919
* @param {inner: boolean, intra: boolean} trainingOpt trainingOpt indicates whether you want to control do the inner or intra dialog training seperately
2020
* @returns {luResult: any, qnaResult: any} trainedResult of luResult and qnaResult or undefined if no results.
2121
*/
22-
train: async function (input, intentName, config, verbose, trainingOpt) {
22+
train: async function (input, intentName, config, verbose, trainingOpt, exclude) {
23+
// get excluded foleders
24+
let excludedFolders = undefined
25+
if (exclude) {
26+
excludedFolders = exclude.split(',').map(e => e.trim())
27+
}
28+
2329
// Get all related file content.
24-
const luContents = await filehelper.getFilesContent(input, fileExtEnum.LUFile)
25-
const qnaContents = await filehelper.getFilesContent(input, fileExtEnum.QnAFile)
30+
const luContents = await filehelper.getFilesContent(input, fileExtEnum.LUFile, excludedFolders)
31+
const qnaContents = await filehelper.getFilesContent(input, fileExtEnum.QnAFile, excludedFolders)
2632
const configContent = await filehelper.getConfigContent(config)
33+
const defaultLocale = 'en-us'
2734

2835
let importResolver = async function (id, idsToFind) {
2936
let importedContents = []
37+
const idWithoutExt = path.basename(id, path.extname(id))
38+
const locale = /\w\.\w/.test(idWithoutExt) ? idWithoutExt.split('.').pop() : defaultLocale;
3039
for (let idx = 0; idx < idsToFind.length; idx++) {
3140
let file = idsToFind[idx]
3241
if (path.isAbsolute(file.filePath)) {
@@ -38,7 +47,16 @@ module.exports = {
3847
} else {
3948
const fileName = path.basename(file.filePath)
4049
const updateImportedContents = async function(typedContents, fileExt) {
41-
const found = typedContents.filter(content => content.id === path.basename(fileName, fileExt))
50+
let found = []
51+
// import resolver should be capable to find implicit import files with locale, for example '[import](b.lu)' is defined in a.en-us.lu, the resolver should find b.en-us.lu
52+
const foundWithLocale = typedContents.filter(content => content.id === `${path.basename(fileName, fileExt)}.${locale}`)
53+
if (foundWithLocale.length > 0) {
54+
found = foundWithLocale
55+
} else {
56+
//if no locale specified file is found, just to check whether there is file without locale matched
57+
found = typedContents.filter(content => content.id === path.basename(fileName, fileExt))
58+
}
59+
4260
if(found.length > 0) {
4361
importedContents.push(...found)
4462
} else {
@@ -57,7 +75,7 @@ module.exports = {
5775
if (fileName.endsWith(fileExtEnum.LUFile)) {
5876
await updateImportedContents(luContents, fileExtEnum.LUFile)
5977
} else if (fileName.endsWith(fileExtEnum.QnAFile)) {
60-
await updateImportedContents(qnaContents, fileExtEnum.LUFile)
78+
await updateImportedContents(qnaContents, fileExtEnum.QnAFile)
6179
}
6280
}
6381
}

packages/lu/src/utils/filehelper.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export async function detectLuContent(stdin: string, input: string) {
171171
return false
172172
}
173173

174-
export async function getFilesContent(input: string, extType: string) {
174+
export async function getFilesContent(input: string, extType: string, ignoredFolders?: string[]) {
175175
let fileStat = await fs.stat(input)
176176
if (fileStat.isFile()) {
177177
const filePath = path.resolve(input)
@@ -182,7 +182,20 @@ export async function getFilesContent(input: string, extType: string) {
182182
if (!fileStat.isDirectory()) {
183183
throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, ' + input + ' is not a folder or does not exist'))
184184
}
185-
const paths = await globby([`**/*${extType}`], {cwd: input, dot: true})
185+
186+
const allPaths = (await globby([`**/*${extType}` ], {cwd: input, dot: true}))
187+
let paths: string[] = []
188+
if (ignoredFolders) {
189+
for (const path of allPaths) {
190+
const isIgnored = ignoredFolders.filter(e => path.startsWith(e)).length > 0
191+
if (!isIgnored) {
192+
paths.push(path)
193+
}
194+
}
195+
} else {
196+
paths = allPaths
197+
}
198+
186199
return Promise.all(paths.map(async (item: string) => {
187200
const itemPath = path.resolve(path.join(input, item))
188201
const content = await getContentFromFile(itemPath)

packages/luis/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ OPTIONS
431431
--[no-]intra-dialog Only do intra dialog cross train
432432
433433
--log Writes out log messages to console
434+
435+
--exclude Excludes given folders under the input directory, for example, --exclude bin,obj,lib, this will ignore the /bin, /obj, /lib folders under the input path
434436
```
435437

436438
_See code: [src/commands/luis/cross-train.ts](https://github.com/microsoft/botframework-cli/tree/master/packages/luis/src/commands/luis/cross-train.ts)_

packages/luis/src/commands/luis/cross-train.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export default class LuisCrossTrain extends Command {
2222
force: flags.boolean({char: 'f', description: 'If --out flag is provided with the path to an existing file, overwrites that file', default: false}),
2323
log: flags.boolean({description: 'Writes out log messages to console', default: false}),
2424
'inner-dialog': flags.boolean({description: 'Only do inner dialog cross train', default: true, allowNo: true}),
25-
'intra-dialog': flags.boolean({description: 'Only do intra dialog cross train', default: true, allowNo: true})
25+
'intra-dialog': flags.boolean({description: 'Only do intra dialog cross train', default: true, allowNo: true}),
26+
exclude: flags.string({description: 'Excludes folders under the input directory, separated by ",". If not specified, all luis and qna files will be included in the cross-train'})
2627
}
2728

2829
async run() {
@@ -46,7 +47,7 @@ export default class LuisCrossTrain extends Command {
4647
intra: flags['intra-dialog']
4748
}
4849

49-
const trainedResult = await crossTrain.train(flags.in, flags.intentName, flags.config, flags.log, trainingOpt)
50+
const trainedResult = await crossTrain.train(flags.in, flags.intentName, flags.config, flags.log, trainingOpt, flags.exclude)
5051

5152
if (flags.out === undefined) {
5253
flags.out = path.join(process.cwd(), 'cross-trained')

packages/luis/test/commands/luis/crossTrain.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,18 @@ describe('luis:cross-train tests for lu and qna contents', () => {
160160
expect(await compareLuFiles('./../../../interruptionGen/application.lu', './../../fixtures/verified/interruption8/application.lu')).to.be.true
161161
expect(await compareLuFiles('./../../../interruptionGen/application.qna', './../../fixtures/verified/interruption8/application.qna')).to.be.true
162162
})
163+
164+
test
165+
.stdout()
166+
.command(['luis:cross-train',
167+
'--in', `${path.join(__dirname, './../../fixtures/testcases/testImportWithLocale')}`,
168+
'--config', `${path.join(__dirname, './../../fixtures/testcases/testImportWithLocale/cross-train.config')}`,
169+
'--out', './interruptionGen',
170+
'--exclude', 'bin',
171+
'--force'])
172+
.it('luis:cross training should able to import files with locale and ignore files under the directory specified', async () => {
173+
expect(await compareLuFiles('./../../../interruptionGen/ChitchatDialog.en-us.lu', './../../fixtures/verified/interruption9/ChitchatDialog.en-us.lu')).to.be.true
174+
expect(await compareLuFiles('./../../../interruptionGen/ChitchatDialog.en-us.qna', './../../fixtures/verified/interruption9/ChitchatDialog.en-us.qna')).to.be.true
175+
expect(fs.existsSync('./../../../interruptionGen/extra.en-us.lu')).to.be.false
176+
})
163177
})

packages/luis/test/fixtures/testcases/testImportWithLocale/ChitchatDialog.en-us.lu

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[import](chitchat_professional.source.qna)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# BotTour
2+
- bot tour
3+
- onboarding
4+
- get started
5+
- start the tour
6+
- what can you do
7+
- what can i ask you
8+
9+
# Cancel
10+
- cancel
11+
- quit
12+
- abort
13+
- exit
14+
- never mind
15+
- forget about it
16+
- just stop already
17+
- end this now
18+
19+
# Help
20+
- help
21+
- im stuck
22+
- how do you work
23+
- what can you do
24+
- what can you help me with
25+
- i need help
26+
- i need some assistance
27+
28+
# Feedback
29+
- i want to give feedback
30+
- i have a problem
31+
- something is broken
32+
- this is a bad experience
33+
- fill out survey
34+
35+
# None
36+
- where is my car?
37+
- I want to order a pizza
38+
- place an item on hold
39+
- Is it going to rain?
40+
- turn on the lights
41+
- check my account balance
42+
- do unicorns really exist
43+
- duck

packages/luis/test/fixtures/testcases/testImportWithLocale/assistant_core.en-us.qna

Whitespace-only changes.

0 commit comments

Comments
 (0)