From f1a92955fbab67c83d7307bde02b17b5799e4f4d Mon Sep 17 00:00:00 2001 From: Tien Suwandy Date: Tue, 14 Sep 2021 14:52:00 -0700 Subject: [PATCH 1/5] surface parsing error to bf cli users --- .../src/commands/orchestrator/create.ts | 2 +- .../orchestratorlib/src/orchestratorhelper.ts | 59 ++++++++++--------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/packages/orchestrator/src/commands/orchestrator/create.ts b/packages/orchestrator/src/commands/orchestrator/create.ts index 1990d4a5b..c4e0624bf 100644 --- a/packages/orchestrator/src/commands/orchestrator/create.ts +++ b/packages/orchestrator/src/commands/orchestrator/create.ts @@ -81,7 +81,7 @@ export default class OrchestratorCreate extends Command { settings.SnapshotPath = snapshotFilePath; settings.persist(); } catch (error) { - throw (new CLIError(error)); + throw (new CLIError(error as Error)); } } diff --git a/packages/orchestratorlib/src/orchestratorhelper.ts b/packages/orchestratorlib/src/orchestratorhelper.ts index 5b3d74d43..2aedb0521 100644 --- a/packages/orchestratorlib/src/orchestratorhelper.ts +++ b/packages/orchestratorlib/src/orchestratorhelper.ts @@ -352,7 +352,7 @@ export class OrchestratorHelper { default: throw new Error(`Unknown file type ${ext}`); } - } catch (error) { + } catch (error: any) { throw new Error(`${error.message}${os.EOL}Failed to parse ${filePath}`); } } @@ -421,15 +421,17 @@ export class OrchestratorHelper { if (!luContent || luContent.length === 0) { return; } - const luObject: any = { - content: luContent, - id: luFile, - }; - const luisObject: any = await LuisBuilder.fromLUAsync([luObject], OrchestratorHelper.findLuFiles); - if (Utility.toPrintDetailedDebuggingLogToConsole) { - UtilityDispatcher.debuggingNamedLog1('OrchestratorHelper.parseLuContent(): calling getIntentsEntitiesUtterances()', luisObject, 'luisObject'); - } try { + const luObject: any = { + content: luContent, + id: luFile, + }; + + const luisObject: any = await LuisBuilder.fromLUAsync([luObject], OrchestratorHelper.findLuFiles); + if (Utility.toPrintDetailedDebuggingLogToConsole) { + UtilityDispatcher.debuggingNamedLog1('OrchestratorHelper.parseLuContent(): calling getIntentsEntitiesUtterances()', luisObject, 'luisObject'); + } + const rvLu: boolean = OrchestratorHelper.getIntentsEntitiesUtterances( luisObject, hierarchicalLabel, @@ -437,12 +439,11 @@ export class OrchestratorHelper { utteranceLabelDuplicateMap, utteranceEntityLabelsMap, utteranceEntityLabelDuplicateMap); - if (!rvLu) { - throw new Error('Failed to parse LUIS or JSON file on intent/entity labels'); - } - } catch (error) { - Utility.debuggingLog(`EXCEPTION calling getIntentsEntitiesUtterances(), error=${error}`); - throw error; + } + catch (error: any) { + Utility.debuggingLog(`EXCEPTION in parseLuContent, error=${error}`); + const errorText: string = error.hasOwnProperty('text') ? error.text : ''; + throw new Error(`Failed parsing lu file ${luFile} - ${errorText}`); } } @@ -602,20 +603,22 @@ export class OrchestratorHelper { return; } - const newlines: string[] = []; - lines.forEach((line: string) => { - if (line.toLowerCase().indexOf('@qna.pair.source =') < 0) { - newlines.push(line); - } - }); - - // Utility.debuggingLog('OrchestratorHelper.parseQnaFile() ready to call QnaMakerBuilder.fromContent()'); - const qnaNormalized: string = Utility.cleanStringOnTabs(newlines.join('\n')); // ---- NOTE ---- QnaMakerBuilder does not like TAB - const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); - if (qnaObject) { + try { + const newlines: string[] = []; + lines.forEach((line: string) => { + if (line.toLowerCase().indexOf('@qna.pair.source =') < 0) { + newlines.push(line); + } + }); + + // Utility.debuggingLog('OrchestratorHelper.parseQnaFile() ready to call QnaMakerBuilder.fromContent()'); + const qnaNormalized: string = Utility.cleanStringOnTabs(newlines.join('\n')); // ---- NOTE ---- QnaMakerBuilder does not like TAB + const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); OrchestratorHelper.getQnaQuestionsAsUtterances(qnaObject, hierarchicalLabel, utteranceLabelsMap, utteranceLabelDuplicateMap); - } else { - throw new Error(`Failed parsing qna file ${qnaFile}`); + } + catch (error: any) { + const errorText: string = error.hasOwnProperty('text') ? error.text : ''; + throw new Error(`Failed parsing qna file ${qnaFile} - ${errorText}`); } } From 5602c930784feeea54e41e1c3dfbf5efcca7487d Mon Sep 17 00:00:00 2001 From: Tien Suwandy Date: Tue, 14 Sep 2021 17:44:44 -0700 Subject: [PATCH 2/5] added tests --- .../test/fixtures/parser/invalid.lu | 17 +++++ .../test/fixtures/parser/invalid.qna | 10 +++ .../test/fixtures/parser/valid.lu | 71 +++++++++++++++++++ .../test/fixtures/parser/valid.qna | 22 ++++++ .../test/orchestratorhelper.test.ts | 63 ++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 packages/orchestratorlib/test/fixtures/parser/invalid.lu create mode 100644 packages/orchestratorlib/test/fixtures/parser/invalid.qna create mode 100644 packages/orchestratorlib/test/fixtures/parser/valid.lu create mode 100644 packages/orchestratorlib/test/fixtures/parser/valid.qna diff --git a/packages/orchestratorlib/test/fixtures/parser/invalid.lu b/packages/orchestratorlib/test/fixtures/parser/invalid.lu new file mode 100644 index 000000000..638d8a8cd --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/invalid.lu @@ -0,0 +1,17 @@ + +> LUIS application information +> !# @app.name = Weather +> !# @app.desc = Weather LUIS application - Bot Builder Samples +> !# @app.versionId = 0.1 +> !# @app.culture = en-us +> !# @app.luis_schema_version = 4.0.0 + + +> # Intent definitions +- current weather ? +- do {@Location=florida} residents usually need ice + +## Get Weather Forecast +- forecast in celcius +- get the forcast for me +- i want to know the temperature at {@Location=death valley} \ No newline at end of file diff --git a/packages/orchestratorlib/test/fixtures/parser/invalid.qna b/packages/orchestratorlib/test/fixtures/parser/invalid.qna new file mode 100644 index 000000000..8d4c5c016 --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/invalid.qna @@ -0,0 +1,10 @@ +**Prompts:** +- [Files that Cannot Sync +](#1) + + + +## ? Files that Cannot Sync +``` +Files that cannot sync. +``` diff --git a/packages/orchestratorlib/test/fixtures/parser/valid.lu b/packages/orchestratorlib/test/fixtures/parser/valid.lu new file mode 100644 index 000000000..e755da466 --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/valid.lu @@ -0,0 +1,71 @@ + +> LUIS application information +> !# @app.name = Weather +> !# @app.desc = Weather LUIS application - Bot Builder Samples +> !# @app.versionId = 0.1 +> !# @app.culture = en-us +> !# @app.luis_schema_version = 4.0.0 + + +> # Intent definitions + +## Get Weather Condition +- current weather ? +- do {@Location=florida} residents usually need ice scrapers +- get {@Location=florence} temperature in september +- get for me the weather conditions in {@Location=sonoma county} +- get the daily temperature {@Location=greenwood indiana} +- get the weather at {@Location=saint george utah} +- how much rain does {@Location=chambersburg} get a year +- show average rainfall for {@Location=boise} +- temperature of {@Location=delhi} in celsius please +- was last year about this time as wet as it is now in the {@Location=south} ? +- what is the rain volume in {@Location=sonoma county} ? +- what to wear in march in {@Location=california} +- what's the weather like in {@Location=minneapolis} +- weather in {@Location_PatternAny} +- how's the weather in {@Location_PatternAny} +- current weather in {@Location_PatternAny} + + +## Get Weather Forecast +- forecast in celcius +- get the forcast for me +- i want to know the temperature at {@Location=death valley} +- provide me by {@Location=toronto} weather please +- show me the forecast at {@Location=alabama} +- soliciting today's weather +- what is the weather in {@Location=redmond} ? +- what is the weather today at 10 day {@Location=durham} ? +- what will the weather be tomorrow in {@Location=new york} ? +- what's the weather going to be like in {@Location=hawaii} ? +- will it be raining in {@Location=ranchi} +- will it rain this weekend +- will it snow today +- what's the forecast for next week in {@Location_PatternAny} +- show me the forecast for {@Location_PatternAny} +- what's the forecast for {@Location_PatternAny} + + +## None + + +> # Entity definitions + +@ ml Location + + +> # PREBUILT Entity definitions + + +> # Phrase list definitions + + +> # List entities + +> # RegEx entities + + +> # Pattern.Any entities + +@ patternany Location_PatternAny diff --git a/packages/orchestratorlib/test/fixtures/parser/valid.qna b/packages/orchestratorlib/test/fixtures/parser/valid.qna new file mode 100644 index 000000000..ff959c68a --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/valid.qna @@ -0,0 +1,22 @@ +# ?store hours +``` +Most our stores are open M-F 9AM-10PM. +``` +**Prompts:** +- [Seattle store](#1) +- [Portland store](#2) + + + +# ?seattle +``` +The Seattle store is open M-F 9AM-10PM. +``` + + + +# ?when is the portland store open +- portland store hours +``` +The Portland store is open 24/7. +``` \ No newline at end of file diff --git a/packages/orchestratorlib/test/orchestratorhelper.test.ts b/packages/orchestratorlib/test/orchestratorhelper.test.ts index 251734514..3464de109 100644 --- a/packages/orchestratorlib/test/orchestratorhelper.test.ts +++ b/packages/orchestratorlib/test/orchestratorhelper.test.ts @@ -588,4 +588,67 @@ describe('Test Suite - orchestratorhelper', () => { assert.ok(result.has('Add item'), 'Incorrect result from getUtteranceLabelsMap, missing Add item utterance'); assert.ok(result.has('delete to do go shopping'), 'Incorrect result from getUtteranceLabelsMap, missing delete to do go shopping utterance'); }); + it('Test.0600 OrchestratorHelper.parseQnaFile()', async () => { + const validFile: string = './test/fixtures/parses/good.qna'; + const inValidFile: string = './test/fixtures/parses/bad.qna'; + + const utteranceLabelsMap: Map> = new Map>(); + const utteranceLabelDuplicateMap: Map> = new Map>(); + try { + await OrchestratorHelper.parseQnaFile( + inValidFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap); + + assert.fail("Invalid syntax exception is not thrown."); + } + catch (e: any) { + assert.ok(e.text.startsWith("Failed parsing qna file") && e.text.startsWith("[ERROR] line ")); + } + + assert.ok(utteranceLabelsMap.size == 0); + + await OrchestratorHelper.parseQnaFile( + validFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap); + assert.ok(utteranceLabelsMap.size > 0); + }); + it('Test.0600 OrchestratorHelper.parseLuFile()', async () => { + const validFile: string = './test/fixtures/parses/good.lu'; + const inValidFile: string = './test/fixtures/parses/bad.lu'; + + const utteranceLabelsMap: Map> = new Map>(); + const utteranceLabelDuplicateMap: Map> = new Map>(); + const utteranceEntityLabelsMap: Map = new Map(); + const utteranceEntityLabelDuplicateMap: Map = new Map(); + + try { + await OrchestratorHelper.parseLuFile( + inValidFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap, + utteranceEntityLabelsMap, + utteranceEntityLabelDuplicateMap); + + assert.fail("Invalid syntax exception is not thrown."); + } + catch (e: any) { + assert.ok(e.text.startsWith("Failed parsing lu file") && e.text.startsWith("[ERROR] line ")); + } + + assert.ok(utteranceLabelsMap.size == 0); + + await OrchestratorHelper.parseLuFile( + validFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap, + utteranceEntityLabelsMap, + utteranceEntityLabelDuplicateMap); + assert.ok(utteranceLabelsMap.size > 0); + }); }); From e83aa212a5b0830a08566d20294e16ab039fe37a Mon Sep 17 00:00:00 2001 From: Tien Suwandy Date: Tue, 14 Sep 2021 22:10:16 -0700 Subject: [PATCH 3/5] fixed lint errors --- .vscode/launch.json | 2 +- .../orchestratorlib/src/orchestratorhelper.ts | 19 +++++------ .../test/orchestratorhelper.test.ts | 34 ++++++------------- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 68765b6af..670087730 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,7 @@ "999999", "--colors", "-g", - ".*addAsync.*" + "Test.0600 OrchestratorHelper.parseLuFile()" ], "cwd": "${workspaceFolder}/packages/orchestratorlib", "internalConsoleOptions": "openOnSessionStart", diff --git a/packages/orchestratorlib/src/orchestratorhelper.ts b/packages/orchestratorlib/src/orchestratorhelper.ts index 2aedb0521..4ec7c86b0 100644 --- a/packages/orchestratorlib/src/orchestratorhelper.ts +++ b/packages/orchestratorlib/src/orchestratorhelper.ts @@ -426,12 +426,10 @@ export class OrchestratorHelper { content: luContent, id: luFile, }; - const luisObject: any = await LuisBuilder.fromLUAsync([luObject], OrchestratorHelper.findLuFiles); if (Utility.toPrintDetailedDebuggingLogToConsole) { UtilityDispatcher.debuggingNamedLog1('OrchestratorHelper.parseLuContent(): calling getIntentsEntitiesUtterances()', luisObject, 'luisObject'); - } - + } const rvLu: boolean = OrchestratorHelper.getIntentsEntitiesUtterances( luisObject, hierarchicalLabel, @@ -439,10 +437,11 @@ export class OrchestratorHelper { utteranceLabelDuplicateMap, utteranceEntityLabelsMap, utteranceEntityLabelDuplicateMap); - } - catch (error: any) { - Utility.debuggingLog(`EXCEPTION in parseLuContent, error=${error}`); - const errorText: string = error.hasOwnProperty('text') ? error.text : ''; + if (!rvLu) { + throw new Error('Failed to parse LUIS or JSON file on intent/entity labels'); + } + } catch (error: any) { + const errorText: string = 'text' in error ? error.text : ''; throw new Error(`Failed parsing lu file ${luFile} - ${errorText}`); } } @@ -610,14 +609,12 @@ export class OrchestratorHelper { newlines.push(line); } }); - // Utility.debuggingLog('OrchestratorHelper.parseQnaFile() ready to call QnaMakerBuilder.fromContent()'); const qnaNormalized: string = Utility.cleanStringOnTabs(newlines.join('\n')); // ---- NOTE ---- QnaMakerBuilder does not like TAB const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); OrchestratorHelper.getQnaQuestionsAsUtterances(qnaObject, hierarchicalLabel, utteranceLabelsMap, utteranceLabelDuplicateMap); - } - catch (error: any) { - const errorText: string = error.hasOwnProperty('text') ? error.text : ''; + } catch (error: any) { + const errorText: string = 'text' in error ? error.text : ''; throw new Error(`Failed parsing qna file ${qnaFile} - ${errorText}`); } } diff --git a/packages/orchestratorlib/test/orchestratorhelper.test.ts b/packages/orchestratorlib/test/orchestratorhelper.test.ts index 3464de109..19b03cbf9 100644 --- a/packages/orchestratorlib/test/orchestratorhelper.test.ts +++ b/packages/orchestratorlib/test/orchestratorhelper.test.ts @@ -425,7 +425,6 @@ describe('Test Suite - orchestratorhelper', () => { assert.ok((utteranceEntityLabelsMap.get(utterance) as Label[]).length === 3, `(utteranceEntityLabelsMap.get(utterance) as Label[]).length=${(utteranceEntityLabelsMap.get(utterance) as Label[]).length}`); }); - it('Test.0300 OrchestratorHelper.getJsonIntentEntityScoresUtterances()', function () { Utility.resetFlagToPrintDebuggingLogToConsole(UnitTestHelper.getDefaultUnitTestDebuggingLogFlag()); this.timeout(UnitTestHelper.getDefaultUnitTestTimeout()); @@ -589,9 +588,8 @@ describe('Test Suite - orchestratorhelper', () => { assert.ok(result.has('delete to do go shopping'), 'Incorrect result from getUtteranceLabelsMap, missing delete to do go shopping utterance'); }); it('Test.0600 OrchestratorHelper.parseQnaFile()', async () => { - const validFile: string = './test/fixtures/parses/good.qna'; - const inValidFile: string = './test/fixtures/parses/bad.qna'; - + const validFile: string = './test/fixtures/parser/valid.qna'; + const inValidFile: string = './test/fixtures/parser/invalid.qna'; const utteranceLabelsMap: Map> = new Map>(); const utteranceLabelDuplicateMap: Map> = new Map>(); try { @@ -600,15 +598,9 @@ describe('Test Suite - orchestratorhelper', () => { '', utteranceLabelsMap, utteranceLabelDuplicateMap); - - assert.fail("Invalid syntax exception is not thrown."); - } - catch (e: any) { - assert.ok(e.text.startsWith("Failed parsing qna file") && e.text.startsWith("[ERROR] line ")); - } - - assert.ok(utteranceLabelsMap.size == 0); - + assert.fail('Invalid syntax exception is not thrown.'); + } catch {} + assert.ok(utteranceLabelsMap.size === 0); await OrchestratorHelper.parseQnaFile( validFile, '', @@ -617,9 +609,8 @@ describe('Test Suite - orchestratorhelper', () => { assert.ok(utteranceLabelsMap.size > 0); }); it('Test.0600 OrchestratorHelper.parseLuFile()', async () => { - const validFile: string = './test/fixtures/parses/good.lu'; - const inValidFile: string = './test/fixtures/parses/bad.lu'; - + const validFile: string = './test/fixtures/parser/valid.lu'; + const inValidFile: string = './test/fixtures/parser/invalid.lu'; const utteranceLabelsMap: Map> = new Map>(); const utteranceLabelDuplicateMap: Map> = new Map>(); const utteranceEntityLabelsMap: Map = new Map(); @@ -633,14 +624,9 @@ describe('Test Suite - orchestratorhelper', () => { utteranceLabelDuplicateMap, utteranceEntityLabelsMap, utteranceEntityLabelDuplicateMap); - - assert.fail("Invalid syntax exception is not thrown."); - } - catch (e: any) { - assert.ok(e.text.startsWith("Failed parsing lu file") && e.text.startsWith("[ERROR] line ")); - } - - assert.ok(utteranceLabelsMap.size == 0); + assert.fail('Invalid syntax exception is not thrown.'); + } catch {} + assert.ok(utteranceLabelsMap.size === 0); await OrchestratorHelper.parseLuFile( validFile, From 0d4da6b0261cf5495297e4a70183da8a73c3f7b0 Mon Sep 17 00:00:00 2001 From: Tien Suwandy Date: Wed, 15 Sep 2021 16:24:48 -0700 Subject: [PATCH 4/5] Update orchestratorhelper.ts --- packages/orchestratorlib/src/orchestratorhelper.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/orchestratorlib/src/orchestratorhelper.ts b/packages/orchestratorlib/src/orchestratorhelper.ts index 4ec7c86b0..1b095c032 100644 --- a/packages/orchestratorlib/src/orchestratorhelper.ts +++ b/packages/orchestratorlib/src/orchestratorhelper.ts @@ -441,8 +441,7 @@ export class OrchestratorHelper { throw new Error('Failed to parse LUIS or JSON file on intent/entity labels'); } } catch (error: any) { - const errorText: string = 'text' in error ? error.text : ''; - throw new Error(`Failed parsing lu file ${luFile} - ${errorText}`); + throw new Error(`Failed parsing lu file ${luFile} ${error.text}`); } } @@ -614,8 +613,7 @@ export class OrchestratorHelper { const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); OrchestratorHelper.getQnaQuestionsAsUtterances(qnaObject, hierarchicalLabel, utteranceLabelsMap, utteranceLabelDuplicateMap); } catch (error: any) { - const errorText: string = 'text' in error ? error.text : ''; - throw new Error(`Failed parsing qna file ${qnaFile} - ${errorText}`); + throw new Error(`Failed parsing qna file ${qnaFile} ${error.text}`); } } From 13d6fca73b08f51af9b185301ad3addeffc9275f Mon Sep 17 00:00:00 2001 From: Tien Suwandy Date: Wed, 15 Sep 2021 21:51:14 -0700 Subject: [PATCH 5/5] Update orchestratorhelper.ts fixed lint error --- packages/orchestratorlib/src/orchestratorhelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/orchestratorlib/src/orchestratorhelper.ts b/packages/orchestratorlib/src/orchestratorhelper.ts index 1b095c032..790a142da 100644 --- a/packages/orchestratorlib/src/orchestratorhelper.ts +++ b/packages/orchestratorlib/src/orchestratorhelper.ts @@ -441,7 +441,7 @@ export class OrchestratorHelper { throw new Error('Failed to parse LUIS or JSON file on intent/entity labels'); } } catch (error: any) { - throw new Error(`Failed parsing lu file ${luFile} ${error.text}`); + throw new Error(`Failed parsing lu file ${luFile} ${error.text}`); } } @@ -613,7 +613,7 @@ export class OrchestratorHelper { const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); OrchestratorHelper.getQnaQuestionsAsUtterances(qnaObject, hierarchicalLabel, utteranceLabelsMap, utteranceLabelDuplicateMap); } catch (error: any) { - throw new Error(`Failed parsing qna file ${qnaFile} ${error.text}`); + throw new Error(`Failed parsing qna file ${qnaFile} ${error.text}`); } }