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

Commit fc92e9b

Browse files
Shuai Wangmunozemilio
andauthored
fix luis cross train unable to reference external files (#1181)
* init * add path resovle * fix import path resolve issue * add tests * fix lint and unused imports * modify config name * retrigger * refactor Co-authored-by: Emilio Munoz <[email protected]>
1 parent a24dad3 commit fc92e9b

File tree

10 files changed

+132
-12
lines changed

10 files changed

+132
-12
lines changed

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

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
*/
55

66
const path = require('path')
7-
const file = require('../../utils/filehelper')
7+
const fs = require('fs-extra')
8+
const filehelper = require('../../utils/filehelper')
89
const fileExtEnum = require('../utils/helpers').FileExtTypeEnum
910
const crossTrainer = require('./crossTrainer')
1011

@@ -20,26 +21,43 @@ module.exports = {
2021
*/
2122
train: async function (input, intentName, config, verbose, trainingOpt) {
2223
// Get all related file content.
23-
const luContents = await file.getFilesContent(input, fileExtEnum.LUFile)
24-
const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile)
25-
const configContent = await file.getConfigContent(config)
24+
const luContents = await filehelper.getFilesContent(input, fileExtEnum.LUFile)
25+
const qnaContents = await filehelper.getFilesContent(input, fileExtEnum.QnAFile)
26+
const configContent = await filehelper.getConfigContent(config)
2627

27-
let importResolver = async function (_, idsToFind) {
28+
let importResolver = async function (id, idsToFind) {
2829
let importedContents = []
2930
for (let idx = 0; idx < idsToFind.length; idx++) {
3031
let file = idsToFind[idx]
3132
if (path.isAbsolute(file.filePath)) {
3233
if (file.filePath.endsWith(fileExtEnum.LUFile)) {
33-
importedContents.push(...await file.getFilesContent(file.filePath, fileExtEnum.LUFile))
34+
importedContents.push(...await filehelper.getFilesContent(file.filePath, fileExtEnum.LUFile))
3435
} else if (file.filePath.endsWith(fileExtEnum.QnAFile)) {
35-
importedContents.push(...await file.getFilesContent(file.filePath, fileExtEnum.QnAFile))
36+
importedContents.push(...await filehelper.getFilesContent(file.filePath, fileExtEnum.QnAFile))
3637
}
3738
} else {
3839
const fileName = path.basename(file.filePath)
40+
const updateImportedContents = async function(typedContents, fileExt) {
41+
const found = typedContents.filter(content => content.id === path.basename(fileName, fileExt))
42+
if(found.length > 0) {
43+
importedContents.push(...found)
44+
} else {
45+
const matchedLuisFiles = typedContents.filter(content => path.basename(content.fullPath) === id)
46+
for (const matchFile of matchedLuisFiles) {
47+
const sourceFileDir = path.dirname(matchFile.fullPath)
48+
const targetPath = path.resolve(sourceFileDir, file.filePath)
49+
if (fs.existsSync(targetPath)) {
50+
const importContent = await filehelper.getFilesContent(targetPath, fileExt)
51+
importedContents.push(...importContent)
52+
}
53+
}
54+
}
55+
}
56+
3957
if (fileName.endsWith(fileExtEnum.LUFile)) {
40-
importedContents.push(...luContents.filter(luContent => luContent.id === path.basename(fileName, fileExtEnum.LUFile)))
58+
await updateImportedContents(luContents, fileExtEnum.LUFile)
4159
} else if (fileName.endsWith(fileExtEnum.QnAFile)) {
42-
importedContents.push(...qnaContents.filter(qnaContent => qnaContent.id === path.basename(fileName, fileExtEnum.QnAFile)))
60+
await updateImportedContents(qnaContents, fileExtEnum.LUFile)
4361
}
4462
}
4563
}
@@ -60,4 +78,4 @@ module.exports = {
6078

6179
return trainedResult
6280
}
63-
}
81+
}

packages/lu/src/utils/filehelper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export async function getFilesContent(input: string, extType: string) {
176176
if (fileStat.isFile()) {
177177
const filePath = path.resolve(input)
178178
const content = await getContentFromFile(input)
179-
return [{id: path.basename(filePath, extType), content}]
179+
return [{id: path.basename(filePath, extType), content, fullPath: filePath}]
180180
}
181181

182182
if (!fileStat.isDirectory()) {
@@ -186,7 +186,7 @@ export async function getFilesContent(input: string, extType: string) {
186186
return Promise.all(paths.map(async (item: string) => {
187187
const itemPath = path.resolve(path.join(input, item))
188188
const content = await getContentFromFile(itemPath)
189-
return {id: path.basename(itemPath, extType), content}
189+
return {id: path.basename(itemPath, extType), content, fullPath: itemPath}
190190
}))
191191
}
192192

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,16 @@ describe('luis:cross-train tests for lu and qna contents', () => {
148148
expect(await compareLuFiles('./../../../interruptionGen/dia1.lu', './../../fixtures/verified/interruption7/dia1.lu')).to.be.true
149149
expect(await compareLuFiles('./../../../interruptionGen/dia1.qna', './../../fixtures/verified/interruption7/dia1.qna')).to.be.true
150150
})
151+
152+
test
153+
.stdout()
154+
.command(['luis:cross-train',
155+
'--in', `${path.join(__dirname, './../../fixtures/testcases/application')}`,
156+
'--config', `${path.join(__dirname, './../../fixtures/testcases/application/cross-train.config')}`,
157+
'--out', './interruptionGen',
158+
'--force'])
159+
.it('luis:cross training should able to import files out of current directory', async () => {
160+
expect(await compareLuFiles('./../../../interruptionGen/application.lu', './../../fixtures/verified/interruption8/application.lu')).to.be.true
161+
expect(await compareLuFiles('./../../../interruptionGen/application.qna', './../../fixtures/verified/interruption8/application.qna')).to.be.true
162+
})
151163
})
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# ExternalIntent
2+
- utterance for ExternalIntent
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# ? Question In ExternalFile.qna
2+
3+
```
4+
Answer to question in ExternalFile.qna
5+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[ExternalFile](../../LUIS/ExternalFile.lu)
2+
3+
# LocalIntent
4+
- utterance for LocalIntent
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[ExternalFile](../../QnaMaker/ExternalFile.qna)
2+
3+
# ? Question In Main application.qna
4+
5+
```
6+
Answer to question in application.qna
7+
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"application": {
3+
"rootDialog": true
4+
}
5+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
> LUIS application information
3+
> !# @app.versionId = 0.1
4+
> !# @app.culture = en-us
5+
> !# @app.luis_schema_version = 3.2.0
6+
7+
8+
> # Intent definitions
9+
10+
# LocalIntent
11+
- utterance for LocalIntent
12+
13+
14+
# ExternalIntent
15+
- utterance for ExternalIntent
16+
17+
18+
> # Entity definitions
19+
20+
21+
> # PREBUILT Entity definitions
22+
23+
24+
> # Phrase list definitions
25+
26+
27+
> # List entities
28+
29+
> # RegEx entities
30+
31+
32+
33+
34+
> Source: cross training. Please do not edit these directly!
35+
# DeferToRecognizer_QnA_application
36+
- Question In Main application.qna
37+
- Question In ExternalFile.qna
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# ? Question In Main application.qna
2+
3+
**Filters:**
4+
- dialogName=application
5+
6+
```
7+
Answer to question in application.qna
8+
```
9+
10+
# ? Question In ExternalFile.qna
11+
12+
**Filters:**
13+
- dialogName=application
14+
15+
```
16+
Answer to question in ExternalFile.qna
17+
```
18+
19+
> Source: cross training. Please do not edit these directly!
20+
> !# @qna.pair.source = crosstrained
21+
22+
# ? utterance for LocalIntent
23+
- utterance for ExternalIntent
24+
25+
**Filters:**
26+
- dialogName=application
27+
28+
```
29+
intent=DeferToRecognizer_LUIS_application
30+
```

0 commit comments

Comments
 (0)