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

Commit fe47f8b

Browse files
committed
Merge branch 'master' into emimunoz/qnamaker
2 parents 040859a + 2058206 commit fe47f8b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2890
-1076
lines changed

packages/luis/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
/yarn.lock
88
node_modules
99
**/.antlr
10+
**/java_generated

packages/luis/src/commands/luis/convert.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export default class LuisConvert extends Command {
5454
result.desc = flags.desc || result.desc || ''
5555
result.culture = flags.culture || result.culture || 'en-us'
5656
result.culture = result.culture.toLowerCase()
57-
if (result.flatListOfEntityAndRoles) delete result.flatListOfEntityAndRoles
5857
result = JSON.stringify(result, null, 2)
5958
}
6059

packages/luis/src/parser/converters/luistoluconverter.js

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const luisFile = require('./../luisfile/parseLuisFile')
66
const helperClasses = require('./../lufile/classes/hclasses')
77
const exception = require('./../lufile/classes/exception')
88
const retCode = require('./../lufile/enums/CLI-errors')
9-
9+
const EntityTypeEnum = require('./../lufile/enums/luisEntityTypes');
1010
module.exports = {
1111
parseLuisFileToLu: async function(file, sort) {
1212
let LUISFileContent = await openFileAndReadContent(file)
@@ -33,6 +33,7 @@ module.exports = {
3333
updateUtterancesList(LUISJSON.patterns, luisObj.intents, 'pattern');
3434
if(luisObj.intents.length >= 0) {
3535
fileContent += NEWLINE;
36+
fileContent += addAppMetaData(LUISJSON);
3637
fileContent += '> # Intent definitions' + NEWLINE + NEWLINE;
3738
// write out intents and utterances..
3839
luisObj.intents.forEach(function(intent) {
@@ -90,21 +91,26 @@ module.exports = {
9091
if(LUISJSON.entities && LUISJSON.entities.length >= 0) {
9192
fileContent += '> # Entity definitions' + NEWLINE + NEWLINE;
9293
LUISJSON.entities.forEach(function(entity) {
93-
// Add inherits information if any
94-
if (entity.inherits !== undefined) {
95-
// > !# @intent.inherits = {name = Web.WebSearch; domain_name = Web; model_name = WebSearch}
96-
fileContent += '> !# @entity.inherits = name : ' + entity.name;
97-
if (entity.inherits.domain_name !== undefined) {
98-
fileContent += '; domain_name : ' + entity.inherits.domain_name;
99-
}
100-
if (entity.inherits.model_name !== undefined) {
101-
fileContent += '; model_name : ' + entity.inherits.model_name;
94+
if (!entity.children || entity.children.length === 0) {
95+
// Add inherits information if any
96+
if (entity.inherits !== undefined) {
97+
// > !# @intent.inherits = {name = Web.WebSearch; domain_name = Web; model_name = WebSearch}
98+
fileContent += '> !# @entity.inherits = name : ' + entity.name;
99+
if (entity.inherits.domain_name !== undefined) {
100+
fileContent += '; domain_name : ' + entity.inherits.domain_name;
101+
}
102+
if (entity.inherits.model_name !== undefined) {
103+
fileContent += '; model_name : ' + entity.inherits.model_name;
104+
}
105+
fileContent += NEWLINE + NEWLINE;
102106
}
107+
fileContent += `@ ml ${entity.name}`;
108+
fileContent += addRolesAndFeatures(entity);
103109
fileContent += NEWLINE + NEWLINE;
110+
} else {
111+
// handle n-depth entity
112+
fileContent += handleNDepthEntity(entity);
104113
}
105-
fileContent += `@ simple ${entity.name}`;
106-
fileContent += addRolesAndFeatures(entity);
107-
fileContent += NEWLINE + NEWLINE;
108114
});
109115
fileContent += NEWLINE;
110116
}
@@ -170,15 +176,69 @@ module.exports = {
170176
fileContent += `@ composite ${composite.name}`;
171177
fileContent += addRolesAndFeatures(composite);
172178
if (composite.children.length > 0) {
173-
fileContent += ` = [${composite.children.join(', ')}]`;
179+
if (typeof composite.children[0] == "object") {
180+
fileContent += ` = [${composite.children.map(item => item.name).join(', ')}]`;
181+
} else {
182+
fileContent += ` = [${composite.children.join(', ')}]`;
183+
}
174184
}
175185
fileContent += NEWLINE;
176186
})
177187
}
178188
return fileContent;
179189
}
180190
}
181-
191+
/**
192+
* Helper to add application inforamtion metadata
193+
* @param {Object} LUISJSON
194+
*/
195+
const addAppMetaData = function(LUISJSON) {
196+
let fileContent = '';
197+
if (LUISJSON.name) fileContent += `> !# @app.name = ${LUISJSON.name}` + NEWLINE;
198+
if (LUISJSON.desc) fileContent += `> !# @app.desc = ${LUISJSON.desc}` + NEWLINE;
199+
if (LUISJSON.versionId) fileContent += `> !# @app.versionId = ${LUISJSON.versionId}` + NEWLINE;
200+
if (LUISJSON.culture) fileContent += `> !# @app.culture = ${LUISJSON.culture}` + NEWLINE;
201+
if (LUISJSON.luis_schema_version) fileContent += `> !# @app.luis_schema_version = ${LUISJSON.luis_schema_version}` + NEWLINE;
202+
return fileContent === '' ? fileContent : `> LUIS application information` + NEWLINE + fileContent + NEWLINE + NEWLINE;
203+
}
204+
/**
205+
* Helper function to handle nDepth entity definition
206+
* @param {Object} entity
207+
*/
208+
const handleNDepthEntity = function(entity) {
209+
let fileContent = '';
210+
const BASE_TAB_STOP = 1;
211+
fileContent += `@ ${EntityTypeEnum.ML} ${entity.name}`;
212+
fileContent += addRolesAndFeatures(entity);
213+
fileContent += NEWLINE;
214+
fileContent += addNDepthChildDefinitions(entity.children, BASE_TAB_STOP, fileContent) + NEWLINE + NEWLINE
215+
return fileContent;
216+
}
217+
/**
218+
* Recursive helper function to add child definitions.
219+
* @param {Object[]} childCollection
220+
* @param {number} tabStop
221+
* @param {string} fileContent
222+
*/
223+
const addNDepthChildDefinitions = function(childCollection, tabStop, fileContent) {
224+
let myFileContent = '';
225+
(childCollection || []).forEach(child => {
226+
myFileContent += "".padStart(tabStop * 4, ' ');
227+
myFileContent += '- @ ';
228+
if (child.instanceOf) {
229+
myFileContent += child.instanceOf;
230+
} else {
231+
myFileContent += EntityTypeEnum.ML;
232+
}
233+
myFileContent += ` ${child.name}`;
234+
myFileContent += addRolesAndFeatures(child);
235+
myFileContent += NEWLINE;
236+
if (child.children && child.children.length !== 0) {
237+
myFileContent += addNDepthChildDefinitions(child.children, ++tabStop, myFileContent);
238+
}
239+
});
240+
return myFileContent;
241+
}
182242
/**
183243
* Helper to construt role and features list for an entity
184244
* @param {Object} entity
@@ -278,17 +338,6 @@ const objectSortByStartPos = function (objectArray) {
278338
return ObjectByStartPos;
279339
}
280340

281-
constructModelDescFromLUISJSON = async function(LUISJSON) {
282-
let modelDesc = NEWLINE;
283-
modelDesc += '> LUIS application information' + NEWLINE;
284-
modelDesc += '> !# @app.name = ' + LUISJSON.name + NEWLINE;
285-
modelDesc += '> !# @app.desc = ' + LUISJSON.desc + NEWLINE;
286-
modelDesc += '> !# @app.culture = ' + LUISJSON.culture + NEWLINE;
287-
modelDesc += '> !# @app.versionId = ' + LUISJSON.versionId + NEWLINE;
288-
modelDesc += '> !# @app.luis_schema_version = ' + LUISJSON.luis_schema_version + NEWLINE;
289-
return modelDesc;
290-
}
291-
292341
/**
293342
* Helper function to return sorted LUIS JSON model
294343
* @param {Object} LUISJSON

packages/luis/src/parser/converters/lutoluisconverter.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
if (haveLUISContent(finalLUISJSON)) {
2626
await luisJSON.validateLUISBlob(finalLUISJSON)
2727
}
28+
checkAndUpdateVersion(finalLUISJSON)
2829
return finalLUISJSON
2930
} catch (err) {
3031
throw(err)
@@ -250,7 +251,31 @@ const mergeResults_closedlists = function (blob, finalCollection, type) {
250251
});
251252
}
252253
}
253-
254+
/**
255+
* Helper to detect luis schema version based on content and update the final payload as needed.
256+
* @param {LUIS} finalLUISJSON
257+
*/
258+
const checkAndUpdateVersion = function(finalLUISJSON) {
259+
// Detect if there is content specific to 5.0.0 schema
260+
// any entity with children
261+
let v5DefFound = false;
262+
v5DefFound = (finalLUISJSON.entities || []).find(i => i.children || i.features) ||
263+
(finalLUISJSON.intents || []).find(i => i.features) ||
264+
(finalLUISJSON.composites || []).find(i => i.features);
265+
if (v5DefFound) {
266+
finalLUISJSON.luis_schema_version = "5.0.0";
267+
if (finalLUISJSON.model_features && finalLUISJSON.model_features.length !== 0) {
268+
finalLUISJSON.phraselists = [];
269+
finalLUISJSON.model_features.forEach(item => finalLUISJSON.phraselists.push(Object.assign({}, item)));
270+
delete finalLUISJSON.model_features;
271+
}
272+
(finalLUISJSON.composites || []).forEach(composite => {
273+
let children = composite.children;
274+
composite.children = [];
275+
children.forEach(c => composite.children.push({name : c}));
276+
})
277+
}
278+
}
254279
/**
255280
* Helper function to see if we have any luis content in the blob
256281
* @param {object} blob Contents of parsed luis blob

packages/luis/src/parser/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55
const modules = {
66
parser: {
7-
parseLuList: require('./converters/lutoluisconverter').parseLuToLuis,
87
parseFile: require('./lufile/parseFileContents').parseFile,
98
validateLUISBlob: require('./luisfile/parseLuisFile').validateLUISBlob
109
},

packages/luis/src/parser/lufile/LUFileLexer.g4

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ fragment WHITESPACE
1414
fragment UTTERANCE_MARK: '-' | '*' | '+';
1515

1616
MODEL_INFO
17-
: '>' WHITESPACE* '!#' ~('\r'|'\n')+
17+
: WS* '>' WHITESPACE* '!#' ~('\r'|'\n')+
1818
;
1919

2020
COMMENT
21-
: '>' ~('\r'|'\n')+ -> skip
21+
: WS* '>' ~('\r'|'\n')+ -> skip
2222
;
2323

2424
WS
25-
: WHITESPACE+ -> skip
25+
: WHITESPACE+
2626
;
2727

2828
NEWLINE
@@ -100,7 +100,7 @@ HAS_FEATURES_LABEL
100100
;
101101

102102
NEW_ENTITY_TYPE_IDENTIFIER
103-
: 'simple'|'list'|'regex'|'prebuilt'|'composite'|'machine-learned'|'patternany'|'phraselist'|'intent'
103+
: 'simple'|'list'|'regex'|'prebuilt'|'composite'|'ml'|'patternany'|'phraselist'|'intent'
104104
;
105105

106106
NEW_ENTITY_IDENTIFIER

packages/luis/src/parser/lufile/LUFileParser.g4

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,15 @@ paragraph
2020
// It's possible that parser doesn't even have to handle NEWLINE,
2121
// but before the syntax is finalized, we still keep the NEWLINE in grammer
2222
newline
23-
: NEWLINE
24-
| EOF
23+
: WS* (NEWLINE | EOF)
2524
;
2625

2726
intentDefinition
2827
: intentNameLine newline intentBody?
2928
;
3029

3130
intentNameLine
32-
: HASH intentName
31+
: WS* HASH intentName
3332
;
3433

3534
intentName
@@ -41,15 +40,15 @@ intentNameIdentifier
4140
;
4241

4342
intentBody
44-
: normalIntentBody
43+
: WS* normalIntentBody
4544
;
4645

4746
normalIntentBody
48-
: (normalIntentString newline)+
47+
: WS* (normalIntentString newline)+
4948
;
5049

5150
normalIntentString
52-
: DASH (WS|TEXT|EXPRESSION|ESCAPE_CHARACTER)*
51+
: WS* DASH (WS|TEXT|EXPRESSION|ESCAPE_CHARACTER)*
5352
;
5453

5554
newEntityDefinition
@@ -61,7 +60,7 @@ newEntityListbody
6160
;
6261

6362
newEntityLine
64-
: AT newEntityType? (newEntityName|newEntityNameWithWS) newEntityRoles? newEntityUsesFeatures? NEW_EQUAL? (newCompositeDefinition|newRegexDefinition)?
63+
: WS* AT newEntityType? (newEntityName|newEntityNameWithWS) newEntityRoles? newEntityUsesFeatures? NEW_EQUAL? (newCompositeDefinition|newRegexDefinition)?
6564
;
6665

6766
newCompositeDefinition
@@ -105,7 +104,7 @@ entityDefinition
105104
;
106105

107106
entityLine
108-
: DOLLAR entityName COLON_MARK entityType
107+
: WS* DOLLAR entityName COLON_MARK entityType
109108
;
110109

111110
entityName
@@ -133,7 +132,7 @@ entityListBody
133132
;
134133

135134
normalItemString
136-
: DASH (WS|TEXT|EXPRESSION)*
135+
: WS* DASH (WS|TEXT|EXPRESSION)*
137136
;
138137

139138
importDefinition
@@ -145,15 +144,15 @@ qnaDefinition
145144
;
146145

147146
qnaQuestion
148-
: QNA questionText newline
147+
: WS* QNA questionText newline
149148
;
150149

151150
questionText
152151
: (WS|QNA_TEXT)*
153152
;
154153

155154
moreQuestionsBody
156-
: (moreQuestion newline)*
155+
: WS* (moreQuestion newline)*
157156
;
158157

159158
moreQuestion
@@ -165,17 +164,17 @@ qnaAnswerBody
165164
;
166165

167166
filterSection
168-
: FILTER_MARK filterLine+
167+
: WS* FILTER_MARK filterLine+
169168
;
170169

171170
filterLine
172-
: DASH (WS|TEXT)* newline
171+
: WS* DASH (WS|TEXT)* newline
173172
;
174173

175174
multiLineAnswer
176-
: MULTI_LINE_TEXT
175+
: WS* MULTI_LINE_TEXT
177176
;
178177

179178
modelInfoDefinition
180-
: MODEL_INFO
179+
: WS* MODEL_INFO
181180
;

packages/luis/src/parser/lufile/classes/hclasses.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ const readerObj = {
140140
constructor(name) {
141141
this.modelName = name ? name : '';
142142
}
143+
},
144+
childEntity: class {
145+
constructor(name, instanceOf, context, children, features) {
146+
this.name = name ? name : '';
147+
this.instanceOf = instanceOf ? instanceOf : '';
148+
this.children = children ? children : [];
149+
this.features = features ? features : '';
150+
this.context = context ? context : '';
151+
}
143152
}
144153
};
145154

packages/luis/src/parser/lufile/enums/luisEntityTypeNameMap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = {
88
'list': 'closedLists',
99
'regex': 'regex_entities',
1010
'composite': 'composites',
11-
'machine-learned': 'entities',
11+
'ml': 'entities',
1212
'patternany':'patternAnyEntities',
1313
'phraselist': 'model_features'
1414
};

packages/luis/src/parser/lufile/enums/luisEntityTypes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = {
88
REGEX: 'regex',
99
PREBUILT: 'prebuilt',
1010
COMPOSITE: 'composite',
11-
ML: 'machine-learned',
11+
ML: 'ml',
1212
PATTERNANY:'patternany',
1313
PHRASELIST: 'phraselist'
1414
};

0 commit comments

Comments
 (0)