From 76505ee238c704076d4737cfffc43a3ea64d72ff Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 3 Mar 2020 22:54:01 +0800 Subject: [PATCH 01/15] update some function to support load file content --- .../lu/src/parser/cross-train/cross-train.js | 28 ++---- .../lu/src/parser/cross-train/crossTrainer.js | 74 +++++++++++++++- packages/lu/src/utils/filehelper.ts | 17 +++- .../parser/cross-train/crossTrainer.test.js | 86 ++++++++++--------- 4 files changed, 140 insertions(+), 65 deletions(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index 31a2865a6..b53ce56db 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -22,30 +22,14 @@ module.exports = { train: async function (input, intentName, configPath) { let trainedResult - // Parse lu and qna objects - const luObjects = await file.getLuObjects(undefined, input, true, fileExtEnum.LUFile) - const qnaObjects = await file.getLuObjects(undefined, input, true, fileExtEnum.QnAFile) + // Get all related file content. + const luContents = await file.getFilesContent(input, fileExtEnum.LUFile); + const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile); + const configContent = await file.getConfigContent(configPath || input); - let configObject - if (configPath && configPath !== '') { - configObject = await file.getConfigObject(configPath) - } else { - configObject = await file.getConfigObject(input) - } - - if (configObject.rootIds.length > 0) { - let crossTrainConfig = { - rootIds: configObject.rootIds, - triggerRules: configObject.triggerRules, - intentName: intentName, - verbose: true - } - - trainedResult = crossTrainer.crossTrain(luObjects, qnaObjects, JSON.stringify(crossTrainConfig)) - } else { - throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'rootDialog property is required in config file')) - } + const configObject = crossTrainer.getConfigObject(configContent, intentName); + trainedResult = crossTrainer.crossTrain(luContents, qnaContents, JSON.stringify(configObject)) return trainedResult }, diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index 17d640cbe..45f40fdff 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -15,6 +15,8 @@ const retCode = require('../utils/enums/CLI-errors'); const NEWLINE = require('os').EOL const path = require('path') const QNA_GENERIC_SOURCE = "custom editorial" +const luObject = require('./../lu/lu') +const LUOptions = require('./../lu/luOptions') module.exports = { /** @@ -25,8 +27,9 @@ module.exports = { * @returns {Map} map of file id and luResource * @throws {exception} throws errors */ - crossTrain: function (luObjectArray, qnaObjectArray, crossTrainConfig) { + crossTrain: function (luContents, qnaContents, crossTrainConfig) { try { + const {luObjectArray, qnaObjectArray} = pretreatment(luContents, qnaContents); const crossTrainConfigObj = JSON.parse(crossTrainConfig) const rootObjectIds = crossTrainConfigObj.rootIds const triggerRules = crossTrainConfigObj.triggerRules @@ -62,9 +65,78 @@ module.exports = { } catch (err) { throw (err) } + }, + + getConfigObject : function (configContent, intentName) { + const configFileDir = path.dirname(configContent.path) + const luConfigContent = configContent.content; + if (luConfigContent && luConfigContent !== '') { + try { + const luConfigObj = JSON.parse(luConfigContent) + for (const rootluFilePath of Object.keys(luConfigObj)) { + const rootLuFileFullPath = path.resolve(configFileDir, rootluFilePath) + const triggerObj = luConfigObj[rootluFilePath] + for (const triggerObjKey of Object.keys(triggerObj)) { + if (triggerObjKey === 'rootDialog') { + if (triggerObj[triggerObjKey]) { + rootLuFiles.push(rootLuFileFullPath) + } + } else if (triggerObjKey === 'triggers') { + const triggers = triggerObj[triggerObjKey] + for (const triggerKey of Object.keys(triggers)) { + const destLuFiles = triggers[triggerKey] instanceof Array ? triggers[triggerKey] : [triggers[triggerKey]] + for (const destLuFile of destLuFiles) { + const destLuFileFullPath = path.resolve(configFileDir, destLuFile) + if (rootLuFileFullPath in finalLuConfigObj) { + const finalDestLuFileToIntent = finalLuConfigObj[rootLuFileFullPath] + finalDestLuFileToIntent[destLuFileFullPath] = triggerKey + } else { + let finalDestLuFileToIntent = Object.create(null) + finalDestLuFileToIntent[destLuFileFullPath] = triggerKey + finalLuConfigObj[rootLuFileFullPath] = finalDestLuFileToIntent + } + } + } + } + } + } + } catch (err) { + throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, `Sorry, invalid cross training config: ${err}`)) + } + } + + if (configObject.rootIds.length > 0) { + let crossTrainConfig = { + rootIds: rootLuFiles, + triggerRules: finalLuConfigObj, + intentName: intentName, + verbose: true + } + + return crossTrainConfig; + } else { + throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'rootDialog property is required in config file')) + } } } +const getParsedObjects = function(contents) { + const parsedObjects = contents.map((content) => { + const opts = new LUOptions(content.path) + return new luObject(content.content, opts); + }) + + return parsedObjects +} + +const pretreatment = function (luContents, qnaContents) { + // Parse lu and qna objects + const luObjectArray = getParsedObjects(luContents); + const qnaObjectArray = getParsedObjects(qnaContents); + + return {luObjectArray, qnaObjectArray} +} + /** * Contruct resource tree to build the father-children relationship among lu files * @param {Map} fileIdToLuResourceMap Map of file id and luResource diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index afaf418c5..6197ca9c6 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -11,9 +11,24 @@ const path = require('path') const helpers = require('./../parser/utils/helpers') const luObject = require('./../parser/lu/lu') const LUOptions = require('./../parser/lu/luOptions') - +const globby = require('globby'); /* tslint:disable:prefer-for-of no-unused*/ +export async function getFilesContent(input: string, extType: string) { + const paths = await globby([`**/*${extType}`], { cwd: input, dot: true }); + return await Promise.all(paths.map(async (item: string) => { + const itemPath = path.resolve(path.join(input, item)) + const content = await getContentFromFile(itemPath); + return {path: itemPath, content} + })) +} + +export async function getConfigContent(input: string) { + const luConfigFile = await getConfigFile(input) + const content = await getContentFromFile(luConfigFile); + return {path: luConfigFile, content}; +} + export async function getLuObjects(stdin: string, input: string | undefined, recurse = false, extType: string | undefined) { let luObjects: any = [] if (stdin) { diff --git a/packages/lu/test/parser/cross-train/crossTrainer.test.js b/packages/lu/test/parser/cross-train/crossTrainer.test.js index 1f4a3f48d..b57596990 100644 --- a/packages/lu/test/parser/cross-train/crossTrainer.test.js +++ b/packages/lu/test/parser/cross-train/crossTrainer.test.js @@ -14,17 +14,17 @@ describe('luis:cross training tests among lu and qna contents', () => { let luContentArray = [] let qnaContentArray = [] - luContentArray.push(new content( + luContentArray.push({content: `# dia1_trigger - book a hotel for me # dia2_trigger - book a flight for me - book a train ticket for me`, - new luOptions('./main/main.lu')) + path:'./main/main.lu'} ) - qnaContentArray.push(new content( + qnaContentArray.push({content: `# ?user guide **Filters:** @@ -38,16 +38,16 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` tell a funny joke \`\`\``, - new luOptions('./main/main.qna')) + path:'./main/main.qna'} ) - luContentArray.push(new content( + luContentArray.push({content: `# dia1_trigger - réserver un hôtel`, - new luOptions('./main/main.fr-fr.lu')) + path: './main/main.fr-fr.lu'} ) - qnaContentArray.push(new content( + qnaContentArray.push({content: `# ?guide de l'utilisateur **Filters:** @@ -56,10 +56,10 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` Voici le [guide de l'utilisateur] (http://contoso.com/userguide.pdf) \`\`\``, - new luOptions('./main/main.fr-fr.qna')) + path:'./main/main.fr-fr.qna'} ) - luContentArray.push(new content( + luContentArray.push({content: `> !# @app.name = my luis application # hotelLevel @@ -67,10 +67,10 @@ describe('luis:cross training tests among lu and qna contents', () => { # hotelLocation - can I book a hotel near space needle`, - new luOptions('./dia1/dia1.lu')) + path:'./dia1/dia1.lu'} ) - qnaContentArray.push(new content( + qnaContentArray.push({content: `> !# @app.desc = description of my luis application > !# @qna.pair.source = xyz @@ -89,37 +89,37 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` of course you can \`\`\``, - new luOptions('./dia1/dia1.qna')) + path:'./dia1/dia1.qna'} ) - luContentArray.push(new content( + luContentArray.push({content: `# hotelLevel - J'ai besoin d'un hôtel quatre étoiles # hotelLocation - puis-je réserver un hôtel près de l'aiguille spatiale`, - new luOptions('./dia1/dia1.fr-fr.lu')) + path:'./dia1/dia1.fr-fr.lu'} ) - qnaContentArray.push(new content( + qnaContentArray.push({content: `# ?raconter la blague \`\`\` ha ha ha \`\`\``, - new luOptions('./dia1/dia1.fr-fr.qna')) + path:'./dia1/dia1.fr-fr.qna'} ) - luContentArray.push(new content( + luContentArray.push({content: `# dia3_trigger - book a flight from {fromLocation = Seattle} to {toLocation = Beijing} # dia4_trigger - book a train ticket from Seattle to Portland`, - new luOptions('./dia2/dia2.lu')) + path:'./dia2/dia2.lu'} ) - qnaContentArray.push(new content( + qnaContentArray.push({content: `# ?sing song \`\`\` sure, I can sing song. @@ -129,30 +129,34 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` ha ha ha \`\`\``, - new luOptions('./dia2/dia2.qna')) + path:'./dia2/dia2.qna'} ) - luContentArray.push(new content( + luContentArray.push( + { + content: `# flightDestination - book a flight to {toLocation = Beijing} # flightTime - which {flightTime} do you prefer`, - new luOptions('./dia3/dia3.lu')) + path:'./dia3/dia3.lu'} ) - qnaContentArray.push(new content( - ``, - new luOptions('./dia3/dia3.qna')) + qnaContentArray.push( + { + content:``, + path: './dia3/dia3.qna' + } ) - luContentArray.push(new content( + luContentArray.push({content: `# railwayStation - which station will you leave from # railwayTime - when do you want to leave from Seattle train station`, - new luOptions('./dia4/dia4.lu')) + path: './dia4/dia4.lu'} ) let crossTrainConfig = { @@ -243,7 +247,7 @@ describe('luis:cross training tests among lu and qna contents', () => { it('luis:cross training can get expected result when nestedIntentSection is enabled', () => { let luContentArray = [] - luContentArray.push(new content( + luContentArray.push({content: `> !# @enableSections = true > !# @enableMergeIntents = true @@ -253,19 +257,19 @@ describe('luis:cross training tests among lu and qna contents', () => { #dia2_trigger - book a hotel for me`, - new luOptions('./main/main.lu')) + path:'./main/main.lu'} ) - luContentArray.push(new content( + luContentArray.push({content: `# FlightTime - which {flightTime} do you prefer`, - new luOptions('./dia1/dia1.lu')) + path:'./dia1/dia1.lu'} ) - luContentArray.push(new content( + luContentArray.push({content: `# HotelLevel - which hotel star do you prefer`, - new luOptions('./dia2/dia2.lu')) + path:'./dia2/dia2.lu'} ) let crossTrainConfig = { @@ -292,31 +296,31 @@ describe('luis:cross training tests among lu and qna contents', () => { it('luis:cross training can get expected result when multiple dialog invocations occur in same trigger', () => { let luContentArray = [] - luContentArray.push(new content( + luContentArray.push({content: `# dia1_trigger - I want to travel to Seattle #dia2_trigger - book a hotel for me`, - new luOptions('./main/main.lu')) + path:'./main/main.lu'} ) - luContentArray.push(new content( + luContentArray.push({content: `# bookFlight - book a flight for me`, - new luOptions('./dia1/dia1.lu')) + path:'./dia1/dia1.lu'} ) - luContentArray.push(new content( + luContentArray.push({content: `# bookTrain - book a train ticket for me`, - new luOptions('./dia2/dia2.lu')) + path:'./dia2/dia2.lu'} ) - luContentArray.push(new content( + luContentArray.push({content: `# HotelLevel - I prefer 4 stars hotel`, - new luOptions('./dia3/dia3.lu')) + path:'./dia3/dia3.lu'} ) let crossTrainConfig = { From b56287d381d6cea0ee1145bb9f43e12612a46450 Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 3 Mar 2020 23:23:44 +0800 Subject: [PATCH 02/15] update some code style --- packages/lu/src/utils/filehelper.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index 6197ca9c6..4d590615a 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -11,22 +11,22 @@ const path = require('path') const helpers = require('./../parser/utils/helpers') const luObject = require('./../parser/lu/lu') const LUOptions = require('./../parser/lu/luOptions') -const globby = require('globby'); +const globby = require('globby') /* tslint:disable:prefer-for-of no-unused*/ export async function getFilesContent(input: string, extType: string) { - const paths = await globby([`**/*${extType}`], { cwd: input, dot: true }); - return await Promise.all(paths.map(async (item: string) => { + const paths = await globby([`**/*${extType}`], {cwd: input, dot: true}) + return Promise.all(paths.map(async (item: string) => { const itemPath = path.resolve(path.join(input, item)) - const content = await getContentFromFile(itemPath); + const content = await getContentFromFile(itemPath) return {path: itemPath, content} })) } export async function getConfigContent(input: string) { const luConfigFile = await getConfigFile(input) - const content = await getContentFromFile(luConfigFile); - return {path: luConfigFile, content}; + const content = await getContentFromFile(luConfigFile) + return {path: luConfigFile, content} } export async function getLuObjects(stdin: string, input: string | undefined, recurse = false, extType: string | undefined) { From 9e45259b8ca367802e623f2c542bbc64ae9d8624 Mon Sep 17 00:00:00 2001 From: leilzh Date: Wed, 4 Mar 2020 16:07:00 +0800 Subject: [PATCH 03/15] update some ref --- .../lu/src/parser/cross-train/cross-train.js | 2 +- .../lu/src/parser/cross-train/crossTrainer.js | 23 +++------------- packages/lu/src/utils/filehelper.ts | 26 ++++++++++++++++++- .../parser/cross-train/crossTrainer.test.js | 6 ++--- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index b53ce56db..e78de24bf 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -29,7 +29,7 @@ module.exports = { const configObject = crossTrainer.getConfigObject(configContent, intentName); - trainedResult = crossTrainer.crossTrain(luContents, qnaContents, JSON.stringify(configObject)) + trainedResult = crossTrainer.crossTrain(luContents, qnaContents, configObject) return trainedResult }, diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index 45f40fdff..94e3dbb5a 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -15,8 +15,6 @@ const retCode = require('../utils/enums/CLI-errors'); const NEWLINE = require('os').EOL const path = require('path') const QNA_GENERIC_SOURCE = "custom editorial" -const luObject = require('./../lu/lu') -const LUOptions = require('./../lu/luOptions') module.exports = { /** @@ -30,11 +28,7 @@ module.exports = { crossTrain: function (luContents, qnaContents, crossTrainConfig) { try { const {luObjectArray, qnaObjectArray} = pretreatment(luContents, qnaContents); - const crossTrainConfigObj = JSON.parse(crossTrainConfig) - const rootObjectIds = crossTrainConfigObj.rootIds - const triggerRules = crossTrainConfigObj.triggerRules - const intentName = crossTrainConfigObj.intentName - const verbose = crossTrainConfigObj.verbose + const {rootIds, triggerRules, intentName, verbose} = crossTrainConfig; // parse lu content to LUResource object let luFileIdToResourceMap = parseAndValidateContent(luObjectArray, verbose) @@ -46,7 +40,7 @@ module.exports = { let resources = constructResoureTree(luFileIdToResourceMap, triggerRules) // do lu cross training from roots. One root one core training - for (const rootObjectId of rootObjectIds) { + for (const rootObjectId of rootIds) { if (resources.some(r => r.id === rootObjectId)) { // do cross training for each root at top level const result = luCrossTrain(rootObjectId, resources, qnaFileIdToResourceMap, intentName) @@ -120,19 +114,10 @@ module.exports = { } } -const getParsedObjects = function(contents) { - const parsedObjects = contents.map((content) => { - const opts = new LUOptions(content.path) - return new luObject(content.content, opts); - }) - - return parsedObjects -} - const pretreatment = function (luContents, qnaContents) { // Parse lu and qna objects - const luObjectArray = getParsedObjects(luContents); - const qnaObjectArray = getParsedObjects(qnaContents); + const luObjectArray = fileHelper.getParsedObjects(luContents); + const qnaObjectArray = fileHelper.getParsedObjects(qnaContents); return {luObjectArray, qnaObjectArray} } diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index 4d590615a..c2f7c180a 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -14,7 +14,22 @@ const LUOptions = require('./../parser/lu/luOptions') const globby = require('globby') /* tslint:disable:prefer-for-of no-unused*/ -export async function getFilesContent(input: string, extType: string) { +export interface FileInfo { + path: string, + content: string, +} + +export async function getFilesContent(input: string, extType: string):Promise { + let fileStat = await fs.stat(input) + if (fileStat.isFile()) { + const filePath = path.resolve(input); + const content = await getContentFromFile(input) + return [{path: filePath, content}] + } + + if (!fileStat.isDirectory()) { + throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, ' + input + ' is not a folder or does not exist')) + } const paths = await globby([`**/*${extType}`], {cwd: input, dot: true}) return Promise.all(paths.map(async (item: string) => { const itemPath = path.resolve(path.join(input, item)) @@ -23,6 +38,15 @@ export async function getFilesContent(input: string, extType: string) { })) } +export function getParsedObjects(contents: FileInfo[]) { + const parsedObjects = contents.map((content) => { + const opts = new LUOptions(content.path) + return new luObject(content.content, opts); + }) + + return parsedObjects +} + export async function getConfigContent(input: string) { const luConfigFile = await getConfigFile(input) const content = await getContentFromFile(luConfigFile) diff --git a/packages/lu/test/parser/cross-train/crossTrainer.test.js b/packages/lu/test/parser/cross-train/crossTrainer.test.js index b57596990..ce5520b67 100644 --- a/packages/lu/test/parser/cross-train/crossTrainer.test.js +++ b/packages/lu/test/parser/cross-train/crossTrainer.test.js @@ -181,7 +181,7 @@ describe('luis:cross training tests among lu and qna contents', () => { verbose: true } - const trainedResult = crossTrainer.crossTrain(luContentArray, qnaContentArray, JSON.stringify(crossTrainConfig)) + const trainedResult = crossTrainer.crossTrain(luContentArray, qnaContentArray, crossTrainConfig) const luResult = trainedResult.luResult const qnaResult = trainedResult.qnaResult @@ -286,7 +286,7 @@ describe('luis:cross training tests among lu and qna contents', () => { verbose: true } - const trainedResult = crossTrainer.crossTrain(luContentArray, [], JSON.stringify(crossTrainConfig)) + const trainedResult = crossTrainer.crossTrain(luContentArray, [], crossTrainConfig) const luResult = trainedResult.luResult assert.equal(luResult.get('./dia2/dia2.lu').Sections[1].Name, '_Interruption') @@ -338,7 +338,7 @@ describe('luis:cross training tests among lu and qna contents', () => { verbose: true } - const trainedResult = crossTrainer.crossTrain(luContentArray, [], JSON.stringify(crossTrainConfig)) + const trainedResult = crossTrainer.crossTrain(luContentArray, [], crossTrainConfig) const luResult = trainedResult.luResult assert.equal(luResult.get('./dia1/dia1.lu').Sections[1].Name, '_Interruption') From 49eec2545440cc8687a96d6f6edc41cffa4dbc3d Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Wed, 4 Mar 2020 17:34:40 +0800 Subject: [PATCH 04/15] optimize config parameter --- .../lu/src/parser/cross-train/cross-train.js | 17 ++-- .../lu/src/parser/cross-train/crossTrainer.js | 38 ++++---- packages/lu/src/utils/filehelper.ts | 90 ++++++++----------- 3 files changed, 61 insertions(+), 84 deletions(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index b53ce56db..4094f5386 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -16,20 +16,19 @@ module.exports = { * Cross train lu and qna files. * @param {string} input input lu and qna files folder. * @param {string} intentName interruption intent name. Default value is _Interruption. - * @param {string} configPath path to config of mapping rules. If undefined, it will read config.json from input folder. + * @param {string} config path to config of mapping rules or mapping rules json content itself. If undefined, it will read config.json from input folder. * @returns {luResult: any, qnaResult: any} trainedResult of luResult and qnaResult or undefined if no results. */ - train: async function (input, intentName, configPath) { - let trainedResult - + train: async function (input, intentName, config) { // Get all related file content. - const luContents = await file.getFilesContent(input, fileExtEnum.LUFile); - const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile); - const configContent = await file.getConfigContent(configPath || input); + const luContents = await file.getFilesContent(input, fileExtEnum.LUFile) + const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile) - const configObject = crossTrainer.getConfigObject(configContent, intentName); + const configContent = config && !fs.existsSync(config) ? config : await file.getConfigContent(config || input) - trainedResult = crossTrainer.crossTrain(luContents, qnaContents, JSON.stringify(configObject)) + const configObject = crossTrainer.getConfigObject(configContent, intentName) + const trainedResult = crossTrainer.crossTrain(luContents, qnaContents, JSON.stringify(configObject)) + return trainedResult }, diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index 45f40fdff..f6f35241f 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -16,13 +16,13 @@ const NEWLINE = require('os').EOL const path = require('path') const QNA_GENERIC_SOURCE = "custom editorial" const luObject = require('./../lu/lu') -const LUOptions = require('./../lu/luOptions') +const luOptions = require('./../lu/luOptions') module.exports = { /** * Do cross training among lu files - * @param {luObject[]} luObjectArray the lu object list to be parsed - * @param {luObject[]} qnaObjectArray the qna Object list to be parsed + * @param {any[]} luContents the lu content array whose element includes path and content + * @param {any[]} qnaContents the qna content array whose element includes path and content * @param {any} crossTrainConfig cross train json config * @returns {Map} map of file id and luResource * @throws {exception} throws errors @@ -67,6 +67,13 @@ module.exports = { } }, + /** + * Get cross train config object based on config content + * @param {any} configContent config content with config path and text content + * @param {string} intentName cross train interruption intent name + * @returns {any} cross train config object + * @throws {exception} throws errors + */ getConfigObject : function (configContent, intentName) { const configFileDir = path.dirname(configContent.path) const luConfigContent = configContent.content; @@ -120,23 +127,6 @@ module.exports = { } } -const getParsedObjects = function(contents) { - const parsedObjects = contents.map((content) => { - const opts = new LUOptions(content.path) - return new luObject(content.content, opts); - }) - - return parsedObjects -} - -const pretreatment = function (luContents, qnaContents) { - // Parse lu and qna objects - const luObjectArray = getParsedObjects(luContents); - const qnaObjectArray = getParsedObjects(qnaContents); - - return {luObjectArray, qnaObjectArray} -} - /** * Contruct resource tree to build the father-children relationship among lu files * @param {Map} fileIdToLuResourceMap Map of file id and luResource @@ -538,3 +528,11 @@ const parseAndValidateContent = function (objectArray, verbose) { return fileIdToResourceMap } + +const pretreatment = function (luContents, qnaContents) { + // Parse lu and qna objects + const luObjectArray = fileHelper.getParsedObjects(luContents) + const qnaObjectArray = fileHelper.getParsedObjects(qnaContents) + + return {luObjectArray, qnaObjectArray} +} \ No newline at end of file diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index 4d590615a..de70c72e6 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -12,21 +12,12 @@ const helpers = require('./../parser/utils/helpers') const luObject = require('./../parser/lu/lu') const LUOptions = require('./../parser/lu/luOptions') const globby = require('globby') + /* tslint:disable:prefer-for-of no-unused*/ -export async function getFilesContent(input: string, extType: string) { - const paths = await globby([`**/*${extType}`], {cwd: input, dot: true}) - return Promise.all(paths.map(async (item: string) => { - const itemPath = path.resolve(path.join(input, item)) - const content = await getContentFromFile(itemPath) - return {path: itemPath, content} - })) -} - -export async function getConfigContent(input: string) { - const luConfigFile = await getConfigFile(input) - const content = await getContentFromFile(luConfigFile) - return {path: luConfigFile, content} +export interface FileInfo { + path: string, + content: string, } export async function getLuObjects(stdin: string, input: string | undefined, recurse = false, extType: string | undefined) { @@ -179,6 +170,31 @@ export async function detectLuContent(stdin: string, input: string) { return false } +export async function getFilesContent(input: string, extType: string):Promise { + let fileStat = await fs.stat(input) + if (fileStat.isFile()) { + const filePath = path.resolve(input) + const content = await getContentFromFile(input) + return [{path: filePath, content}] + } + + if (!fileStat.isDirectory()) { + throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, ' + input + ' is not a folder or does not exist')) + } + const paths = await globby([`**/*${extType}`], {cwd: input, dot: true}) + return Promise.all(paths.map(async (item: string) => { + const itemPath = path.resolve(path.join(input, item)) + const content = await getContentFromFile(itemPath) + return {path: itemPath, content} + })) +} + +export async function getConfigContent(input: string) { + const luConfigFile = await getConfigFile(input) + const content = await getContentFromFile(luConfigFile) + return {path: luConfigFile, content} +} + async function getConfigFile(input: string): Promise { let fileStat = await fs.stat(input) if (fileStat.isFile()) { @@ -198,49 +214,13 @@ async function getConfigFile(input: string): Promise { return defaultConfigFile } -export async function getConfigObject(input: string) { - const luConfigFile = await getConfigFile(input) - - let finalLuConfigObj = Object.create(null) - let rootLuFiles: string[] = [] - const configFileDir = path.dirname(luConfigFile) - const luConfigContent = await getContentFromFile(luConfigFile) - if (luConfigContent && luConfigContent !== '') { - try { - const luConfigObj = JSON.parse(luConfigContent) - for (const rootluFilePath of Object.keys(luConfigObj)) { - const rootLuFileFullPath = path.resolve(configFileDir, rootluFilePath) - const triggerObj = luConfigObj[rootluFilePath] - for (const triggerObjKey of Object.keys(triggerObj)) { - if (triggerObjKey === 'rootDialog') { - if (triggerObj[triggerObjKey]) { - rootLuFiles.push(rootLuFileFullPath) - } - } else if (triggerObjKey === 'triggers') { - const triggers = triggerObj[triggerObjKey] - for (const triggerKey of Object.keys(triggers)) { - const destLuFiles = triggers[triggerKey] instanceof Array ? triggers[triggerKey] : [triggers[triggerKey]] - for (const destLuFile of destLuFiles) { - const destLuFileFullPath = path.resolve(configFileDir, destLuFile) - if (rootLuFileFullPath in finalLuConfigObj) { - const finalDestLuFileToIntent = finalLuConfigObj[rootLuFileFullPath] - finalDestLuFileToIntent[destLuFileFullPath] = triggerKey - } else { - let finalDestLuFileToIntent = Object.create(null) - finalDestLuFileToIntent[destLuFileFullPath] = triggerKey - finalLuConfigObj[rootLuFileFullPath] = finalDestLuFileToIntent - } - } - } - } - } - } - } catch (err) { - throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, `Sorry, invalid cross training config: ${err}`)) - } - } +export function getParsedObjects(contents: FileInfo[]) { + const parsedObjects = contents.map((content) => { + const opts = new LUOptions(content.path) + return new luObject(content.content, opts) + }) - return {rootIds: rootLuFiles, triggerRules: finalLuConfigObj} + return parsedObjects } export function parseJSON(input: string, appType: string) { From c647f8c8fcf02e49a2ed092205dd52d878992193 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Wed, 4 Mar 2020 17:45:21 +0800 Subject: [PATCH 05/15] add fileHelper.ts --- packages/lu/src/utils/filehelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index de70c72e6..5855ce305 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -170,7 +170,7 @@ export async function detectLuContent(stdin: string, input: string) { return false } -export async function getFilesContent(input: string, extType: string):Promise { +export async function getFilesContent(input: string, extType: string): Promise { let fileStat = await fs.stat(input) if (fileStat.isFile()) { const filePath = path.resolve(input) @@ -215,7 +215,7 @@ async function getConfigFile(input: string): Promise { } export function getParsedObjects(contents: FileInfo[]) { - const parsedObjects = contents.map((content) => { + const parsedObjects = contents.map(content => { const opts = new LUOptions(content.path) return new luObject(content.content, opts) }) From 8bf0c442f45abda39952e98bfd3cc631c4e74bf6 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Wed, 4 Mar 2020 17:47:08 +0800 Subject: [PATCH 06/15] fix typo --- packages/lu/src/parser/cross-train/cross-train.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index fc1aadc0d..e0677cf57 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -27,7 +27,8 @@ module.exports = { const configObject = crossTrainer.getConfigObject(configContent, intentName); - trainedResult = crossTrainer.crossTrain(luContents, qnaContents, configObject) + const trainedResult = crossTrainer.crossTrain(luContents, qnaContents, configObject) + return trainedResult }, From 744bdee1759ddd78a1f9f7cb7db5906e89638cf6 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Wed, 4 Mar 2020 17:56:46 +0800 Subject: [PATCH 07/15] remove semicolon --- packages/lu/src/parser/cross-train/cross-train.js | 4 ++-- packages/lu/src/parser/cross-train/crossTrainer.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index e0677cf57..e0d731410 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -8,7 +8,7 @@ const path = require('path') const file = require('../../utils/filehelper') const fileExtEnum = require('../utils/helpers').FileExtTypeEnum const exception = require('../utils/exception') -const retCode = require('../utils/enums/CLI-errors'); +const retCode = require('../utils/enums/CLI-errors') const crossTrainer = require('./crossTrainer') module.exports = { @@ -25,7 +25,7 @@ module.exports = { const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile) const configContent = config && !fs.existsSync(config) ? config : await file.getConfigContent(config || input) - const configObject = crossTrainer.getConfigObject(configContent, intentName); + const configObject = crossTrainer.getConfigObject(configContent, intentName) const trainedResult = crossTrainer.crossTrain(luContents, qnaContents, configObject) diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index ea34b7ac8..27d235ecd 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -11,7 +11,7 @@ const LUResource = require('../lufile/luResource') const DiagnosticSeverity = require('../lufile/diagnostic').DiagnosticSeverity const fileHelper = require('../../utils/filehelper') const exception = require('../utils/exception') -const retCode = require('../utils/enums/CLI-errors'); +const retCode = require('../utils/enums/CLI-errors') const NEWLINE = require('os').EOL const path = require('path') const QNA_GENERIC_SOURCE = "custom editorial" @@ -27,8 +27,8 @@ module.exports = { */ crossTrain: function (luContents, qnaContents, crossTrainConfig) { try { - const {luObjectArray, qnaObjectArray} = pretreatment(luContents, qnaContents); - const {rootIds, triggerRules, intentName, verbose} = crossTrainConfig; + const {luObjectArray, qnaObjectArray} = pretreatment(luContents, qnaContents) + const {rootIds, triggerRules, intentName, verbose} = crossTrainConfig // parse lu content to LUResource object let luFileIdToResourceMap = parseAndValidateContent(luObjectArray, verbose) @@ -70,7 +70,7 @@ module.exports = { */ getConfigObject : function (configContent, intentName) { const configFileDir = path.dirname(configContent.path) - const luConfigContent = configContent.content; + const luConfigContent = configContent.content if (luConfigContent && luConfigContent !== '') { try { const luConfigObj = JSON.parse(luConfigContent) @@ -114,7 +114,7 @@ module.exports = { verbose: true } - return crossTrainConfig; + return crossTrainConfig } else { throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'rootDialog property is required in config file')) } From a44db2df32e38823d3f4228a6e2b94b962af4147 Mon Sep 17 00:00:00 2001 From: leilzh Date: Wed, 4 Mar 2020 18:05:34 +0800 Subject: [PATCH 08/15] add the object --- packages/lu/src/parser/cross-train/crossTrainer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index 27d235ecd..70c538ef1 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -69,6 +69,8 @@ module.exports = { * @throws {exception} throws errors */ getConfigObject : function (configContent, intentName) { + let finalLuConfigObj = Object.create(null) + let rootLuFiles = [] const configFileDir = path.dirname(configContent.path) const luConfigContent = configContent.content if (luConfigContent && luConfigContent !== '') { From bbcafb451788fbefb2834e2cc5f75053580ce63d Mon Sep 17 00:00:00 2001 From: leilzh Date: Wed, 4 Mar 2020 18:10:40 +0800 Subject: [PATCH 09/15] change the value --- packages/lu/src/parser/cross-train/crossTrainer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index 70c538ef1..fcabc8cda 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -108,7 +108,7 @@ module.exports = { } } - if (configObject.rootIds.length > 0) { + if (rootLuFiles.length > 0) { let crossTrainConfig = { rootIds: rootLuFiles, triggerRules: finalLuConfigObj, From 642d34dbe3ab132b2ab6bf294374e2ff02490598 Mon Sep 17 00:00:00 2001 From: leilzh Date: Wed, 4 Mar 2020 18:34:42 +0800 Subject: [PATCH 10/15] make all the path the same parttern --- packages/lu/src/utils/filehelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index 5855ce305..0a0918a67 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -216,7 +216,7 @@ async function getConfigFile(input: string): Promise { export function getParsedObjects(contents: FileInfo[]) { const parsedObjects = contents.map(content => { - const opts = new LUOptions(content.path) + const opts = new LUOptions(path.resolve(content.path)) return new luObject(content.content, opts) }) From 66ecf8dd466570ad373099d4aa027c866b55faa5 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Thu, 5 Mar 2020 10:40:01 +0800 Subject: [PATCH 11/15] optimize --- .../lu/src/parser/cross-train/crossTrainer.js | 61 ---- packages/lu/src/utils/filehelper.ts | 68 +++- .../parser/cross-train/crossTrainer.test.js | 337 +++++++++--------- 3 files changed, 235 insertions(+), 231 deletions(-) diff --git a/packages/lu/src/parser/cross-train/crossTrainer.js b/packages/lu/src/parser/cross-train/crossTrainer.js index fcabc8cda..dccd06d9e 100644 --- a/packages/lu/src/parser/cross-train/crossTrainer.js +++ b/packages/lu/src/parser/cross-train/crossTrainer.js @@ -59,67 +59,6 @@ module.exports = { } catch (err) { throw (err) } - }, - - /** - * Get cross train config object based on config content - * @param {any} configContent config content with config path and text content - * @param {string} intentName cross train interruption intent name - * @returns {any} cross train config object - * @throws {exception} throws errors - */ - getConfigObject : function (configContent, intentName) { - let finalLuConfigObj = Object.create(null) - let rootLuFiles = [] - const configFileDir = path.dirname(configContent.path) - const luConfigContent = configContent.content - if (luConfigContent && luConfigContent !== '') { - try { - const luConfigObj = JSON.parse(luConfigContent) - for (const rootluFilePath of Object.keys(luConfigObj)) { - const rootLuFileFullPath = path.resolve(configFileDir, rootluFilePath) - const triggerObj = luConfigObj[rootluFilePath] - for (const triggerObjKey of Object.keys(triggerObj)) { - if (triggerObjKey === 'rootDialog') { - if (triggerObj[triggerObjKey]) { - rootLuFiles.push(rootLuFileFullPath) - } - } else if (triggerObjKey === 'triggers') { - const triggers = triggerObj[triggerObjKey] - for (const triggerKey of Object.keys(triggers)) { - const destLuFiles = triggers[triggerKey] instanceof Array ? triggers[triggerKey] : [triggers[triggerKey]] - for (const destLuFile of destLuFiles) { - const destLuFileFullPath = path.resolve(configFileDir, destLuFile) - if (rootLuFileFullPath in finalLuConfigObj) { - const finalDestLuFileToIntent = finalLuConfigObj[rootLuFileFullPath] - finalDestLuFileToIntent[destLuFileFullPath] = triggerKey - } else { - let finalDestLuFileToIntent = Object.create(null) - finalDestLuFileToIntent[destLuFileFullPath] = triggerKey - finalLuConfigObj[rootLuFileFullPath] = finalDestLuFileToIntent - } - } - } - } - } - } - } catch (err) { - throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, `Sorry, invalid cross training config: ${err}`)) - } - } - - if (rootLuFiles.length > 0) { - let crossTrainConfig = { - rootIds: rootLuFiles, - triggerRules: finalLuConfigObj, - intentName: intentName, - verbose: true - } - - return crossTrainConfig - } else { - throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'rootDialog property is required in config file')) - } } } diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index 0a0918a67..3ace1f96a 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -15,8 +15,8 @@ const globby = require('globby') /* tslint:disable:prefer-for-of no-unused*/ -export interface FileInfo { - path: string, +export interface ContentInfo { + id: string, content: string, } @@ -170,12 +170,12 @@ export async function detectLuContent(stdin: string, input: string) { return false } -export async function getFilesContent(input: string, extType: string): Promise { +export async function getFilesContent(input: string, extType: string): Promise { let fileStat = await fs.stat(input) if (fileStat.isFile()) { const filePath = path.resolve(input) const content = await getContentFromFile(input) - return [{path: filePath, content}] + return [{id: filePath, content}] } if (!fileStat.isDirectory()) { @@ -185,7 +185,7 @@ export async function getFilesContent(input: string, extType: string): Promise { const itemPath = path.resolve(path.join(input, item)) const content = await getContentFromFile(itemPath) - return {path: itemPath, content} + return {id: itemPath, content} })) } @@ -214,15 +214,69 @@ async function getConfigFile(input: string): Promise { return defaultConfigFile } -export function getParsedObjects(contents: FileInfo[]) { +export function getParsedObjects(contents: ContentInfo[]) { const parsedObjects = contents.map(content => { - const opts = new LUOptions(path.resolve(content.path)) + const opts = new LUOptions(content.id) return new luObject(content.content, opts) }) return parsedObjects } +export function getConfigObject(configContent: any, intentName: string) { + let finalLuConfigObj = Object.create(null) + let rootLuFiles: string[] = [] + const configFileDir = path.dirname(configContent.path) + const luConfigContent = configContent.content + if (luConfigContent && luConfigContent !== '') { + try { + const luConfigObj = JSON.parse(luConfigContent) + for (const rootluFilePath of Object.keys(luConfigObj)) { + const rootLuFileFullPath = path.resolve(configFileDir, rootluFilePath) + const triggerObj = luConfigObj[rootluFilePath] + for (const triggerObjKey of Object.keys(triggerObj)) { + if (triggerObjKey === 'rootDialog') { + if (triggerObj[triggerObjKey]) { + rootLuFiles.push(rootLuFileFullPath) + } + } else if (triggerObjKey === 'triggers') { + const triggers = triggerObj[triggerObjKey] + for (const triggerKey of Object.keys(triggers)) { + const destLuFiles = triggers[triggerKey] instanceof Array ? triggers[triggerKey] : [triggers[triggerKey]] + for (const destLuFile of destLuFiles) { + const destLuFileFullPath = path.resolve(configFileDir, destLuFile) + if (rootLuFileFullPath in finalLuConfigObj) { + const finalDestLuFileToIntent = finalLuConfigObj[rootLuFileFullPath] + finalDestLuFileToIntent[destLuFileFullPath] = triggerKey + } else { + let finalDestLuFileToIntent = Object.create(null) + finalDestLuFileToIntent[destLuFileFullPath] = triggerKey + finalLuConfigObj[rootLuFileFullPath] = finalDestLuFileToIntent + } + } + } + } + } + } + } catch (err) { + throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, `Sorry, invalid cross training config: ${err}`)) + } + } + + if (rootLuFiles.length > 0) { + let crossTrainConfig = { + rootIds: rootLuFiles, + triggerRules: finalLuConfigObj, + intentName, + verbose: true + } + + return crossTrainConfig + } else { + throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'rootDialog property is required in config file')) + } +} + export function parseJSON(input: string, appType: string) { try { return JSON.parse(input) diff --git a/packages/lu/test/parser/cross-train/crossTrainer.test.js b/packages/lu/test/parser/cross-train/crossTrainer.test.js index ce5520b67..109f11413 100644 --- a/packages/lu/test/parser/cross-train/crossTrainer.test.js +++ b/packages/lu/test/parser/cross-train/crossTrainer.test.js @@ -5,8 +5,6 @@ const assert = require('chai').assert const crossTrainer = require('../../../src/parser/cross-train/crossTrainer') -const content = require('../../../src/parser/lu/lu') -const luOptions = require('../../../src/parser/lu/luOptions') const NEWLINE = require('os').EOL describe('luis:cross training tests among lu and qna contents', () => { @@ -14,150 +12,156 @@ describe('luis:cross training tests among lu and qna contents', () => { let luContentArray = [] let qnaContentArray = [] - luContentArray.push({content: - `# dia1_trigger - - book a hotel for me - - # dia2_trigger - - book a flight for me - - book a train ticket for me`, - path:'./main/main.lu'} + luContentArray.push({ + content: + `# dia1_trigger + - book a hotel for me + + # dia2_trigger + - book a flight for me + - book a train ticket for me`, + id: './main/main.lu'}) + + qnaContentArray.push({ + content: + `# ?user guide + + **Filters:** + - aa=bb + + \`\`\` + Here is the [user guide](http://contoso.com/userguide.pdf) + \`\`\` + + # ?tell joke + \`\`\` + tell a funny joke + \`\`\``, + id: './main/main.qna'} ) - qnaContentArray.push({content: - `# ?user guide - - **Filters:** - - aa=bb - - \`\`\` - Here is the [user guide](http://contoso.com/userguide.pdf) - \`\`\` - - # ?tell joke - \`\`\` - tell a funny joke - \`\`\``, - path:'./main/main.qna'} + luContentArray.push({ + content: + `# dia1_trigger + - réserver un hôtel`, + id: './main/main.fr-fr.lu'} ) - luContentArray.push({content: - `# dia1_trigger - - réserver un hôtel`, - path: './main/main.fr-fr.lu'} + qnaContentArray.push({ + content: + `# ?guide de l'utilisateur + + **Filters:** + - aa=bb + + \`\`\` + Voici le [guide de l'utilisateur] (http://contoso.com/userguide.pdf) + \`\`\``, + id: './main/main.fr-fr.qna'} ) - qnaContentArray.push({content: - `# ?guide de l'utilisateur - - **Filters:** - - aa=bb - - \`\`\` - Voici le [guide de l'utilisateur] (http://contoso.com/userguide.pdf) - \`\`\``, - path:'./main/main.fr-fr.qna'} + luContentArray.push({ + content: + `> !# @app.name = my luis application + + # hotelLevel + - I need a four star hotel + + # hotelLocation + - can I book a hotel near space needle`, + id: './dia1/dia1.lu'} ) - luContentArray.push({content: - `> !# @app.name = my luis application - - # hotelLevel - - I need a four star hotel - - # hotelLocation - - can I book a hotel near space needle`, - path:'./dia1/dia1.lu'} + qnaContentArray.push({ + content: + `> !# @app.desc = description of my luis application + + > !# @qna.pair.source = xyz + + + # ?tell joke + - tell me a joke + + \`\`\` + ha ha ha + \`\`\` + **Prompts:** + - [flight booking](#?-book-flight) \`context-only\` + + # ?can I book a hotel near space needle + \`\`\` + of course you can + \`\`\``, + id: './dia1/dia1.qna'} ) - qnaContentArray.push({content: - `> !# @app.desc = description of my luis application - - > !# @qna.pair.source = xyz - - - # ?tell joke - - tell me a joke - - \`\`\` - ha ha ha - \`\`\` - **Prompts:** - - [flight booking](#?-book-flight) \`context-only\` - - # ?can I book a hotel near space needle - \`\`\` - of course you can - \`\`\``, - path:'./dia1/dia1.qna'} + luContentArray.push({ + content: + `# hotelLevel + - J'ai besoin d'un hôtel quatre étoiles + + # hotelLocation + - puis-je réserver un hôtel près de l'aiguille spatiale`, + id: './dia1/dia1.fr-fr.lu'} ) - luContentArray.push({content: - `# hotelLevel - - J'ai besoin d'un hôtel quatre étoiles - - # hotelLocation - - puis-je réserver un hôtel près de l'aiguille spatiale`, - path:'./dia1/dia1.fr-fr.lu'} + qnaContentArray.push({ + content: + `# ?raconter la blague + + \`\`\` + ha ha ha + \`\`\``, + id: './dia1/dia1.fr-fr.qna'} ) - qnaContentArray.push({content: - `# ?raconter la blague - - \`\`\` - ha ha ha - \`\`\``, - path:'./dia1/dia1.fr-fr.qna'} + luContentArray.push({ + content: + `# dia3_trigger + - book a flight from {fromLocation = Seattle} to {toLocation = Beijing} + + # dia4_trigger + - book a train ticket from Seattle to Portland`, + id: './dia2/dia2.lu'} ) - luContentArray.push({content: - `# dia3_trigger - - book a flight from {fromLocation = Seattle} to {toLocation = Beijing} - - # dia4_trigger - - book a train ticket from Seattle to Portland`, - path:'./dia2/dia2.lu'} + qnaContentArray.push({ + content: + `# ?sing song + \`\`\` + sure, I can sing song. + \`\`\` + + # ?tell a joke + \`\`\` + ha ha ha + \`\`\``, + id: './dia2/dia2.qna'} ) - qnaContentArray.push({content: - `# ?sing song - \`\`\` - sure, I can sing song. - \`\`\` - - # ?tell a joke - \`\`\` - ha ha ha - \`\`\``, - path:'./dia2/dia2.qna'} + luContentArray.push({ + content: + `# flightDestination + - book a flight to {toLocation = Beijing} + + # flightTime + - which {flightTime} do you prefer`, + id: './dia3/dia3.lu'} ) - luContentArray.push( - { - content: - `# flightDestination - - book a flight to {toLocation = Beijing} - - # flightTime - - which {flightTime} do you prefer`, - path:'./dia3/dia3.lu'} - ) + qnaContentArray.push({ + content: ``, + id: './dia3/dia3.qna' + }) - qnaContentArray.push( - { - content:``, - path: './dia3/dia3.qna' - } - ) - - luContentArray.push({content: - `# railwayStation - - which station will you leave from - - # railwayTime - - when do you want to leave from Seattle train station`, - path: './dia4/dia4.lu'} - ) + luContentArray.push({ + content: + `# railwayStation + - which station will you leave from + + # railwayTime + - when do you want to leave from Seattle train station`, + id: './dia4/dia4.lu'}) let crossTrainConfig = { rootIds: [ @@ -247,29 +251,32 @@ describe('luis:cross training tests among lu and qna contents', () => { it('luis:cross training can get expected result when nestedIntentSection is enabled', () => { let luContentArray = [] - luContentArray.push({content: - `> !# @enableSections = true - > !# @enableMergeIntents = true - - # dia1_trigger - ## bookFlight - - book a flight for me - - #dia2_trigger - - book a hotel for me`, - path:'./main/main.lu'} + luContentArray.push({ + content: + `> !# @enableSections = true + > !# @enableMergeIntents = true + + # dia1_trigger + ## bookFlight + - book a flight for me + + #dia2_trigger + - book a hotel for me`, + id:'./main/main.lu'} ) - luContentArray.push({content: - `# FlightTime - - which {flightTime} do you prefer`, - path:'./dia1/dia1.lu'} + luContentArray.push({ + content: + `# FlightTime + - which {flightTime} do you prefer`, + id:'./dia1/dia1.lu'} ) - luContentArray.push({content: - `# HotelLevel - - which hotel star do you prefer`, - path:'./dia2/dia2.lu'} + luContentArray.push({ + content: + `# HotelLevel + - which hotel star do you prefer`, + id:'./dia2/dia2.lu'} ) let crossTrainConfig = { @@ -296,31 +303,35 @@ describe('luis:cross training tests among lu and qna contents', () => { it('luis:cross training can get expected result when multiple dialog invocations occur in same trigger', () => { let luContentArray = [] - luContentArray.push({content: - `# dia1_trigger - - I want to travel to Seattle - - #dia2_trigger - - book a hotel for me`, - path:'./main/main.lu'} + luContentArray.push({ + content: + `# dia1_trigger + - I want to travel to Seattle + + #dia2_trigger + - book a hotel for me`, + id: './main/main.lu'} ) - luContentArray.push({content: - `# bookFlight - - book a flight for me`, - path:'./dia1/dia1.lu'} + luContentArray.push({ + content: + `# bookFlight + - book a flight for me`, + id: './dia1/dia1.lu'} ) - luContentArray.push({content: - `# bookTrain - - book a train ticket for me`, - path:'./dia2/dia2.lu'} + luContentArray.push({ + content: + `# bookTrain + - book a train ticket for me`, + id: './dia2/dia2.lu'} ) - luContentArray.push({content: - `# HotelLevel - - I prefer 4 stars hotel`, - path:'./dia3/dia3.lu'} + luContentArray.push({ + content: + `# HotelLevel + - I prefer 4 stars hotel`, + id: './dia3/dia3.lu'} ) let crossTrainConfig = { From b7c025043b35cc84f65c125680bd7d48371f5777 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Thu, 5 Mar 2020 11:32:36 +0800 Subject: [PATCH 12/15] adjust test cases to use file name as id --- .../parser/cross-train/crossTrainer.test.js | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/packages/lu/test/parser/cross-train/crossTrainer.test.js b/packages/lu/test/parser/cross-train/crossTrainer.test.js index 109f11413..686d814e4 100644 --- a/packages/lu/test/parser/cross-train/crossTrainer.test.js +++ b/packages/lu/test/parser/cross-train/crossTrainer.test.js @@ -20,7 +20,7 @@ describe('luis:cross training tests among lu and qna contents', () => { # dia2_trigger - book a flight for me - book a train ticket for me`, - id: './main/main.lu'}) + id: 'main.lu'}) qnaContentArray.push({ content: @@ -37,14 +37,14 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` tell a funny joke \`\`\``, - id: './main/main.qna'} + id: 'main.qna'} ) luContentArray.push({ content: `# dia1_trigger - réserver un hôtel`, - id: './main/main.fr-fr.lu'} + id: 'main.fr-fr.lu'} ) qnaContentArray.push({ @@ -57,7 +57,7 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` Voici le [guide de l'utilisateur] (http://contoso.com/userguide.pdf) \`\`\``, - id: './main/main.fr-fr.qna'} + id: 'main.fr-fr.qna'} ) luContentArray.push({ @@ -69,7 +69,7 @@ describe('luis:cross training tests among lu and qna contents', () => { # hotelLocation - can I book a hotel near space needle`, - id: './dia1/dia1.lu'} + id: 'dia1.lu'} ) qnaContentArray.push({ @@ -92,7 +92,7 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` of course you can \`\`\``, - id: './dia1/dia1.qna'} + id: 'dia1.qna'} ) luContentArray.push({ @@ -102,7 +102,7 @@ describe('luis:cross training tests among lu and qna contents', () => { # hotelLocation - puis-je réserver un hôtel près de l'aiguille spatiale`, - id: './dia1/dia1.fr-fr.lu'} + id: 'dia1.fr-fr.lu'} ) qnaContentArray.push({ @@ -112,7 +112,7 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` ha ha ha \`\`\``, - id: './dia1/dia1.fr-fr.qna'} + id: 'dia1.fr-fr.qna'} ) luContentArray.push({ @@ -122,7 +122,7 @@ describe('luis:cross training tests among lu and qna contents', () => { # dia4_trigger - book a train ticket from Seattle to Portland`, - id: './dia2/dia2.lu'} + id: 'dia2.lu'} ) qnaContentArray.push({ @@ -136,7 +136,7 @@ describe('luis:cross training tests among lu and qna contents', () => { \`\`\` ha ha ha \`\`\``, - id: './dia2/dia2.qna'} + id: 'dia2.qna'} ) luContentArray.push({ @@ -146,12 +146,12 @@ describe('luis:cross training tests among lu and qna contents', () => { # flightTime - which {flightTime} do you prefer`, - id: './dia3/dia3.lu'} + id: 'dia3.lu'} ) qnaContentArray.push({ content: ``, - id: './dia3/dia3.qna' + id: 'dia3.qna' }) luContentArray.push({ @@ -161,24 +161,24 @@ describe('luis:cross training tests among lu and qna contents', () => { # railwayTime - when do you want to leave from Seattle train station`, - id: './dia4/dia4.lu'}) + id: 'dia4.lu'}) let crossTrainConfig = { rootIds: [ - './main/main.lu', - './main/main.fr-fr.lu' + 'main.lu', + 'main.fr-fr.lu' ], triggerRules: { - './main/main.lu': { - './dia1/dia1.lu': 'dia1_trigger', - './dia2/dia2.lu': 'dia2_trigger' + 'main.lu': { + 'dia1.lu': 'dia1_trigger', + 'dia2.lu': 'dia2_trigger' }, - './dia2/dia2.lu': { - './dia3/dia3.lu': 'dia3_trigger', - './dia4/dia4.lu': 'dia4_trigger' + 'dia2.lu': { + 'dia3.lu': 'dia3_trigger', + 'dia4.lu': 'dia4_trigger' }, - './main/main.fr-fr.lu': { - './dia1/dia1.fr-fr.lu': 'dia1_trigger' + 'main.fr-fr.lu': { + 'dia1.fr-fr.lu': 'dia1_trigger' } }, intentName: '_Interruption', @@ -189,62 +189,62 @@ describe('luis:cross training tests among lu and qna contents', () => { const luResult = trainedResult.luResult const qnaResult = trainedResult.qnaResult - assert.equal(luResult.get('./main/main.lu').Sections[2].Name, 'DeferToRecognizer_QnA_main') - assert.equal(luResult.get('./main/main.lu').Sections[2].Body, `- user guide${NEWLINE}- tell joke`) + assert.equal(luResult.get('main.lu').Sections[2].Name, 'DeferToRecognizer_QnA_main') + assert.equal(luResult.get('main.lu').Sections[2].Body, `- user guide${NEWLINE}- tell joke`) - assert.equal(qnaResult.get('./main/main.qna').Sections[2].Answer, 'intent=DeferToRecognizer_LUIS_main') - assert.equal(qnaResult.get('./main/main.qna').Sections[2].FilterPairs[0].key, 'dialogName') - assert.equal(qnaResult.get('./main/main.qna').Sections[2].FilterPairs[0].value, 'main') - assert.equal(qnaResult.get('./main/main.qna').Sections[2].Questions[0], 'book a hotel for me') - assert.equal(qnaResult.get('./main/main.qna').Sections[2].Questions[2], 'book a train ticket for me') + assert.equal(qnaResult.get('main.qna').Sections[2].Answer, 'intent=DeferToRecognizer_LUIS_main') + assert.equal(qnaResult.get('main.qna').Sections[2].FilterPairs[0].key, 'dialogName') + assert.equal(qnaResult.get('main.qna').Sections[2].FilterPairs[0].value, 'main') + assert.equal(qnaResult.get('main.qna').Sections[2].Questions[0], 'book a hotel for me') + assert.equal(qnaResult.get('main.qna').Sections[2].Questions[2], 'book a train ticket for me') - assert.equal(luResult.get('./dia1/dia1.lu').Sections[0].ModelInfo, '> !# @app.name = my luis application') - assert.equal(luResult.get('./dia1/dia1.lu').Sections[3].Name, '_Interruption') - assert.equal(luResult.get('./dia1/dia1.lu').Sections[3].Body, `- book a flight for me${NEWLINE}- book a train ticket for me${NEWLINE}- user guide`) - assert.equal(luResult.get('./dia1/dia1.lu').Sections[4].Name, 'DeferToRecognizer_QnA_dia1') - assert.equal(luResult.get('./dia1/dia1.lu').Sections[4].Body, `- tell joke${NEWLINE}- tell me a joke`) + assert.equal(luResult.get('dia1.lu').Sections[0].ModelInfo, '> !# @app.name = my luis application') + assert.equal(luResult.get('dia1.lu').Sections[3].Name, '_Interruption') + assert.equal(luResult.get('dia1.lu').Sections[3].Body, `- book a flight for me${NEWLINE}- book a train ticket for me${NEWLINE}- user guide`) + assert.equal(luResult.get('dia1.lu').Sections[4].Name, 'DeferToRecognizer_QnA_dia1') + assert.equal(luResult.get('dia1.lu').Sections[4].Body, `- tell joke${NEWLINE}- tell me a joke`) - assert.equal(qnaResult.get('./dia1/dia1.qna').Sections[0].ModelInfo, '> !# @app.desc = description of my luis application') - assert.equal(qnaResult.get('./dia1/dia1.qna').Sections[1].FilterPairs[0].key, 'dialogName') - assert.equal(qnaResult.get('./dia1/dia1.qna').Sections[1].FilterPairs[0].value, 'dia1') - assert.equal(qnaResult.get('./dia1/dia1.qna').Sections[1].promptsText[0], '[flight booking](#?-book-flight) `context-only`') - assert.equal(qnaResult.get('./dia1/dia1.qna').Sections[3].Questions.join(', '), 'I need a four star hotel, book a flight for me, book a train ticket for me, user guide') + assert.equal(qnaResult.get('dia1.qna').Sections[0].ModelInfo, '> !# @app.desc = description of my luis application') + assert.equal(qnaResult.get('dia1.qna').Sections[1].FilterPairs[0].key, 'dialogName') + assert.equal(qnaResult.get('dia1.qna').Sections[1].FilterPairs[0].value, 'dia1') + assert.equal(qnaResult.get('dia1.qna').Sections[1].promptsText[0], '[flight booking](#?-book-flight) `context-only`') + assert.equal(qnaResult.get('dia1.qna').Sections[3].Questions.join(', '), 'I need a four star hotel, book a flight for me, book a train ticket for me, user guide') - assert.equal(luResult.get('./dia2/dia2.lu').Sections[2].Name, '_Interruption') - assert.equal(luResult.get('./dia2/dia2.lu').Sections[2].Body, `- book a hotel for me${NEWLINE}- user guide${NEWLINE}- tell joke`) - assert.equal(luResult.get('./dia2/dia2.lu').Sections[3].Name, 'DeferToRecognizer_QnA_dia2') - assert.equal(luResult.get('./dia2/dia2.lu').Sections[3].Body, `- sing song${NEWLINE}- tell a joke`) + assert.equal(luResult.get('dia2.lu').Sections[2].Name, '_Interruption') + assert.equal(luResult.get('dia2.lu').Sections[2].Body, `- book a hotel for me${NEWLINE}- user guide${NEWLINE}- tell joke`) + assert.equal(luResult.get('dia2.lu').Sections[3].Name, 'DeferToRecognizer_QnA_dia2') + assert.equal(luResult.get('dia2.lu').Sections[3].Body, `- sing song${NEWLINE}- tell a joke`) - assert.equal(qnaResult.get('./dia2/dia2.qna').Sections[0].FilterPairs[0].key, 'dialogName') - assert.equal(qnaResult.get('./dia2/dia2.qna').Sections[0].FilterPairs[0].value, 'dia2') - assert.equal(qnaResult.get('./dia2/dia2.qna').Sections[2].Questions.join(', '), 'book a flight from Seattle to Beijing, book a train ticket from Seattle to Portland, book a hotel for me, user guide, tell joke') + assert.equal(qnaResult.get('dia2.qna').Sections[0].FilterPairs[0].key, 'dialogName') + assert.equal(qnaResult.get('dia2.qna').Sections[0].FilterPairs[0].value, 'dia2') + assert.equal(qnaResult.get('dia2.qna').Sections[2].Questions.join(', '), 'book a flight from Seattle to Beijing, book a train ticket from Seattle to Portland, book a hotel for me, user guide, tell joke') - assert.equal(luResult.get('./dia3/dia3.lu').Sections.length, 3) - assert.equal(luResult.get('./dia3/dia3.lu').Sections[2].Name, '_Interruption') - assert.equal(luResult.get('./dia3/dia3.lu').Sections[2].Body, `- book a train ticket from Seattle to Portland${NEWLINE}- book a hotel for me${NEWLINE}- user guide${NEWLINE}- tell joke${NEWLINE}- sing song${NEWLINE}- tell a joke`) + assert.equal(luResult.get('dia3.lu').Sections.length, 3) + assert.equal(luResult.get('dia3.lu').Sections[2].Name, '_Interruption') + assert.equal(luResult.get('dia3.lu').Sections[2].Body, `- book a train ticket from Seattle to Portland${NEWLINE}- book a hotel for me${NEWLINE}- user guide${NEWLINE}- tell joke${NEWLINE}- sing song${NEWLINE}- tell a joke`) - assert.equal(qnaResult.get('./dia3/dia3.qna').Sections.length, 0) + assert.equal(qnaResult.get('dia3.qna').Sections.length, 0) - assert.equal(luResult.get('./dia4/dia4.lu').Sections.length, 3) - assert.equal(luResult.get('./dia4/dia4.lu').Sections[2].Name, '_Interruption') - assert.equal(luResult.get('./dia4/dia4.lu').Sections[2].Body, `- book a flight from Seattle to Beijing${NEWLINE}- book a hotel for me${NEWLINE}- user guide${NEWLINE}- tell joke${NEWLINE}- sing song${NEWLINE}- tell a joke`) + assert.equal(luResult.get('dia4.lu').Sections.length, 3) + assert.equal(luResult.get('dia4.lu').Sections[2].Name, '_Interruption') + assert.equal(luResult.get('dia4.lu').Sections[2].Body, `- book a flight from Seattle to Beijing${NEWLINE}- book a hotel for me${NEWLINE}- user guide${NEWLINE}- tell joke${NEWLINE}- sing song${NEWLINE}- tell a joke`) - assert.equal(luResult.get('./main/main.fr-fr.lu').Sections[1].Name, 'DeferToRecognizer_QnA_main') - assert.equal(luResult.get('./main/main.fr-fr.lu').Sections[1].Body, `- guide de l'utilisateur`) + assert.equal(luResult.get('main.fr-fr.lu').Sections[1].Name, 'DeferToRecognizer_QnA_main') + assert.equal(luResult.get('main.fr-fr.lu').Sections[1].Body, `- guide de l'utilisateur`) - assert.equal(qnaResult.get('./main/main.fr-fr.qna').Sections[1].Answer, 'intent=DeferToRecognizer_LUIS_main') - assert.equal(qnaResult.get('./main/main.fr-fr.qna').Sections[1].FilterPairs[0].key, 'dialogName') - assert.equal(qnaResult.get('./main/main.fr-fr.qna').Sections[1].FilterPairs[0].value, 'main') - assert.equal(qnaResult.get('./main/main.fr-fr.qna').Sections[1].Questions.length, 1) - assert.equal(qnaResult.get('./main/main.fr-fr.qna').Sections[1].Questions[0], 'réserver un hôtel') + assert.equal(qnaResult.get('main.fr-fr.qna').Sections[1].Answer, 'intent=DeferToRecognizer_LUIS_main') + assert.equal(qnaResult.get('main.fr-fr.qna').Sections[1].FilterPairs[0].key, 'dialogName') + assert.equal(qnaResult.get('main.fr-fr.qna').Sections[1].FilterPairs[0].value, 'main') + assert.equal(qnaResult.get('main.fr-fr.qna').Sections[1].Questions.length, 1) + assert.equal(qnaResult.get('main.fr-fr.qna').Sections[1].Questions[0], 'réserver un hôtel') - assert.equal(luResult.get('./dia1/dia1.fr-fr.lu').Sections[2].Name, '_Interruption') - assert.equal(luResult.get('./dia1/dia1.fr-fr.lu').Sections[2].Body, `- guide de l'utilisateur`) - assert.equal(luResult.get('./dia1/dia1.fr-fr.lu').Sections[3].Name, 'DeferToRecognizer_QnA_dia1') - assert.equal(luResult.get('./dia1/dia1.fr-fr.lu').Sections[3].Body, `- raconter la blague`) + assert.equal(luResult.get('dia1.fr-fr.lu').Sections[2].Name, '_Interruption') + assert.equal(luResult.get('dia1.fr-fr.lu').Sections[2].Body, `- guide de l'utilisateur`) + assert.equal(luResult.get('dia1.fr-fr.lu').Sections[3].Name, 'DeferToRecognizer_QnA_dia1') + assert.equal(luResult.get('dia1.fr-fr.lu').Sections[3].Body, `- raconter la blague`) - assert.equal(qnaResult.get('./dia1/dia1.fr-fr.qna').Sections[1].Questions.join(', '), 'J\'ai besoin d\'un hôtel quatre étoiles, puis-je réserver un hôtel près de l\'aiguille spatiale, guide de l\'utilisateur') + assert.equal(qnaResult.get('dia1.fr-fr.qna').Sections[1].Questions.join(', '), 'J\'ai besoin d\'un hôtel quatre étoiles, puis-je réserver un hôtel près de l\'aiguille spatiale, guide de l\'utilisateur') }) From 9ab76d4dabbdc9f2149289d7806981ce219b5a03 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Thu, 5 Mar 2020 13:20:10 +0800 Subject: [PATCH 13/15] fix typo --- packages/lu/src/parser/cross-train/cross-train.js | 2 +- packages/lu/src/utils/filehelper.ts | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index e0d731410..fc9621949 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -25,7 +25,7 @@ module.exports = { const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile) const configContent = config && !fs.existsSync(config) ? config : await file.getConfigContent(config || input) - const configObject = crossTrainer.getConfigObject(configContent, intentName) + const configObject = file.getConfigObject(configContent, intentName) const trainedResult = crossTrainer.crossTrain(luContents, qnaContents, configObject) diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index 3ace1f96a..f5379f986 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -15,11 +15,6 @@ const globby = require('globby') /* tslint:disable:prefer-for-of no-unused*/ -export interface ContentInfo { - id: string, - content: string, -} - export async function getLuObjects(stdin: string, input: string | undefined, recurse = false, extType: string | undefined) { let luObjects: any = [] if (stdin) { @@ -170,7 +165,7 @@ export async function detectLuContent(stdin: string, input: string) { return false } -export async function getFilesContent(input: string, extType: string): Promise { +export async function getFilesContent(input: string, extType: string) { let fileStat = await fs.stat(input) if (fileStat.isFile()) { const filePath = path.resolve(input) @@ -192,7 +187,7 @@ export async function getFilesContent(input: string, extType: string): Promise { @@ -214,7 +209,7 @@ async function getConfigFile(input: string): Promise { return defaultConfigFile } -export function getParsedObjects(contents: ContentInfo[]) { +export function getParsedObjects(contents: {id: string, content: string}[]) { const parsedObjects = contents.map(content => { const opts = new LUOptions(content.id) return new luObject(content.content, opts) From 13300c59a30cdc07f54a6a9d2a9a349bfa75b872 Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Thu, 5 Mar 2020 14:38:24 +0800 Subject: [PATCH 14/15] fix config id issue --- packages/lu/src/parser/cross-train/cross-train.js | 2 +- packages/lu/src/utils/filehelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lu/src/parser/cross-train/cross-train.js b/packages/lu/src/parser/cross-train/cross-train.js index fc9621949..37b85fa02 100644 --- a/packages/lu/src/parser/cross-train/cross-train.js +++ b/packages/lu/src/parser/cross-train/cross-train.js @@ -23,7 +23,7 @@ module.exports = { // Get all related file content. const luContents = await file.getFilesContent(input, fileExtEnum.LUFile) const qnaContents = await file.getFilesContent(input, fileExtEnum.QnAFile) - const configContent = config && !fs.existsSync(config) ? config : await file.getConfigContent(config || input) + const configContent = config && !fs.existsSync(config) ? {id: path.join(input, 'config.json'), content: config} : await file.getConfigContent(config || input) const configObject = file.getConfigObject(configContent, intentName) diff --git a/packages/lu/src/utils/filehelper.ts b/packages/lu/src/utils/filehelper.ts index f5379f986..91e954871 100644 --- a/packages/lu/src/utils/filehelper.ts +++ b/packages/lu/src/utils/filehelper.ts @@ -221,7 +221,7 @@ export function getParsedObjects(contents: {id: string, content: string}[]) { export function getConfigObject(configContent: any, intentName: string) { let finalLuConfigObj = Object.create(null) let rootLuFiles: string[] = [] - const configFileDir = path.dirname(configContent.path) + const configFileDir = path.dirname(configContent.id) const luConfigContent = configContent.content if (luConfigContent && luConfigContent !== '') { try { From 764a7374f91dafa75d97bae970564334601ff6be Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Thu, 5 Mar 2020 15:24:14 +0800 Subject: [PATCH 15/15] move globby from dev dependency to dependency --- packages/lu/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lu/package.json b/packages/lu/package.json index a81e6b31e..1c5dd0bda 100644 --- a/packages/lu/package.json +++ b/packages/lu/package.json @@ -43,6 +43,7 @@ "delay": "^4.3.0", "fs-extra": "^8.1.0", "get-stdin": "^6.0.0", + "globby": "^10.0.1", "intercept-stdout": "^0.1.2", "lodash": "^4.17.15", "node-fetch": "^2.1.2", @@ -57,7 +58,6 @@ "@types/mocha": "^5.2.7", "@types/node": "^10.14.15", "chai": "^4.2.0", - "globby": "^10.0.1", "mocha": "^6.2.2", "nock": "^11.7.0", "nyc": "^14.1.1",