Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions packages/lu/src/parser/luis/luisGenBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ const buildVersion6 = function(luisApp) {
let result = new LuisGen()
try {
result.intents = processIntents(luisApp.intents);
[result.entities, result.composites] = extractEntitiesV6(luisApp.entities);
result.prebuiltEntities = extractEntities(luisApp.prebuiltEntities, true);
result.closedLists = extractEntities(luisApp.closedLists);
[result.entities, result.composites] = extractEntitiesV6(luisApp.entities, result.closedLists);
result.prebuiltEntities = extractEntities(luisApp.prebuiltEntities, true);
result.regex_entities = extractEntities(luisApp.regex_entities);
result.patternAnyEntities = extractEntities(luisApp.patternAnyEntities);
} catch (err) {
Expand Down Expand Up @@ -99,13 +99,19 @@ const extractEntities = function(entities, builtIn = false) {
return result;
}

const extractEntitiesV6 = function(entities) {
const extractEntitiesV6 = function(entities, closedLists) {
// This method provides a simplified topological sort to
// solve potential instanceOf dependecies in the v6 entities

const simpleEntitiesResult = [];
const compositeEntitiesResult = [];
const simpleEntitiesWithType = {};

// Add 'closedList' entities as valid types for instanceOf
closedLists.forEach(listEntity => {
simpleEntitiesWithType[listEntity] = 'list'
});

const resolveEntityType = function(entityName) {
const entityStack = [];
let entityType = simpleEntitiesWithType[entityName];
Expand Down
11 changes: 11 additions & 0 deletions packages/luis/test/commands/luis/generate/cs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,15 @@ describe('luis:generate:cs', () => {
.it('Generates class based on luis schema v6 correctly', async () => {
await compareSourceFiles('../../../fixtures/generate/SchemaV6.cs', '../../../fixtures/generate/results/SchemaV6.cs')
})

test
.stdout()
.command(['luis:generate:cs',
'--in',
`${path.join(__dirname, '../../../fixtures/generate/V6AnyEntityAsInstanceOf.json')}`,
'--out',
`${path.join(__dirname, '../../../fixtures/generate/results/V6AnyEntityAsInstanceOf.cs')}`])
.it('Generates class based on V6 with entity instanceOf referencing a closedList', async () => {
await compareSourceFiles('../../../fixtures/generate/V6AnyEntityAsInstanceOf.cs', '../../../fixtures/generate/results/V6AnyEntityAsInstanceOf.cs')
})
})
113 changes: 113 additions & 0 deletions packages/luis/test/fixtures/generate/V6AnyEntityAsInstanceOf.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// <auto-generated>
// Code generated by luis:generate:cs
// Tool github: https://github.com/microsoft/botframework-cli
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.
// </auto-generated>
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.AI.Luis;
namespace Luis
{
public partial class MusicSkill: IRecognizerConvert
{
[JsonProperty("text")]
public string Text;

[JsonProperty("alteredText")]
public string AlteredText;

public enum Intent {
PlayMusic
};
[JsonProperty("intents")]
public Dictionary<Intent, IntentScore> Intents;

public class _Entities
{
// Lists
public string[][] GenreList;


// Composites
public class _InstanceMusicParent
{
public InstanceData[] beforeMusic;
public InstanceData[] afterMusic;
public InstanceData[] music;
public InstanceData[] inBetweenMusic;
public InstanceData[] genre;
}
public class MusicParentClass
{
public string[] beforeMusic;
public string[] afterMusic;
public string[] music;
public string[] inBetweenMusic;
public string[][] genre;
[JsonProperty("$instance")]
public _InstanceMusicParent _instance;
}
public MusicParentClass[] MusicParent;

// Instance
public class _Instance
{
public InstanceData[] GenreList;
public InstanceData[] MusicParent;
public InstanceData[] afterMusic;
public InstanceData[] beforeMusic;
public InstanceData[] genre;
public InstanceData[] inBetweenMusic;
public InstanceData[] music;
}
[JsonProperty("$instance")]
public _Instance _instance;
}
[JsonProperty("entities")]
public _Entities Entities;

[JsonExtensionData(ReadData = true, WriteData = true)]
public IDictionary<string, object> Properties {get; set; }

public void Convert(dynamic result)
{
var app = JsonConvert.DeserializeObject<MusicSkill>(
JsonConvert.SerializeObject(
result,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Error = OnError }
)
);
Text = app.Text;
AlteredText = app.AlteredText;
Intents = app.Intents;
Entities = app.Entities;
Properties = app.Properties;
}

private static void OnError(object sender, ErrorEventArgs args)
{
// If needed, put your custom error logic here
Console.WriteLine(args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
}

public (Intent intent, double score) TopIntent()
{
Intent maxIntent = Intent.None;
var max = 0.0;
foreach (var entry in Intents)
{
if (entry.Value.Score > max)
{
maxIntent = entry.Key;
max = entry.Value.Score.Value;
}
}
return (maxIntent, max);
}
}
}
207 changes: 207 additions & 0 deletions packages/luis/test/fixtures/generate/V6AnyEntityAsInstanceOf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
{
"intents": [
{
"name": "PlayMusic"
}
],
"entities": [
{
"name": "MusicParent",
"roles": [],
"children": [
{
"name": "beforeMusic",
"instanceOf": null,
"children": []
},
{
"name": "afterMusic",
"instanceOf": null,
"children": []
},
{
"name": "music",
"instanceOf": null,
"children": []
},
{
"name": "inBetweenMusic",
"instanceOf": null,
"children": []
},
{
"name": "genre",
"instanceOf": "GenreList",
"children": []
}
]
}
],
"composites": [],
"closedLists": [
{
"name": "GenreList",
"subLists": [
{
"canonicalForm": "genre_list",
"list": [
"schlager",
"deathrash metal",
"boi",
"drill music"
]
}
],
"roles": []
}
],
"regex_entities": [],
"regex_features": [],
"utterances": [
{
"text": "play adeles latest album",
"intent": "PlayMusic",
"entities": [
{
"entity": "beforeMusic",
"startPos": 0,
"endPos": 3
},
{
"entity": "music",
"startPos": 5,
"endPos": 10
},
{
"entity": "afterMusic",
"startPos": 12,
"endPos": 23
},
{
"entity": "MusicParent",
"startPos": 0,
"endPos": 23
}
]
},
{
"text": "play prince",
"intent": "PlayMusic",
"entities": [
{
"entity": "beforeMusic",
"startPos": 0,
"endPos": 3
},
{
"entity": "music",
"startPos": 5,
"endPos": 10
},
{
"entity": "MusicParent",
"startPos": 0,
"endPos": 10
}
]
},
{
"text": "play schlager",
"intent": "PlayMusic",
"entities": [
{
"entity": "beforeMusic",
"startPos": 0,
"endPos": 3
},
{
"entity": "genre",
"startPos": 5,
"endPos": 12
},
{
"entity": "MusicParent",
"startPos": 0,
"endPos": 12
}
]
},
{
"text": "can you play rihanna please?",
"intent": "PlayMusic",
"entities": [
{
"entity": "beforeMusic",
"startPos": 0,
"endPos": 11
},
{
"entity": "inBetweenMusic",
"startPos": 13,
"endPos": 19
},
{
"entity": "afterMusic",
"startPos": 21,
"endPos": 27
},
{
"entity": "MusicParent",
"startPos": 0,
"endPos": 27
}
]
},
{
"text": "can you play boi",
"intent": "PlayMusic",
"entities": [
{
"entity": "beforeMusic",
"startPos": 0,
"endPos": 11
},
{
"entity": "genre",
"startPos": 13,
"endPos": 15
},
{
"entity": "MusicParent",
"startPos": 0,
"endPos": 15
}
]
},
{
"text": "can you play crazy beautiful",
"intent": "PlayMusic",
"entities": [
{
"entity": "beforeMusic",
"startPos": 0,
"endPos": 11
},
{
"entity": "music",
"startPos": 13,
"endPos": 27
},
{
"entity": "MusicParent",
"startPos": 0,
"endPos": 27
}
]
}
],
"patterns": [],
"patternAnyEntities": [],
"prebuiltEntities": [],
"luis_schema_version": "6.0.0",
"versionId": "0.1",
"name": "MusicSkill",
"desc": "",
"culture": "en-us",
"phraselists": []
}