Skip to content
This repository has been archived by the owner on Aug 31, 2022. It is now read-only.

Commit

Permalink
updated the LUIS TryFindEntity extension to only return an entity by …
Browse files Browse the repository at this point in the history
…… (#4509)

* updated the LUIS TryFindEntity extension to only return an entity by type if its start index doesn't overlap with the start and end index of other LuisResult Entities.  I came across this issue when working with an intent that accepts both a date and number.  If the intent message is 'make a reservation tomorrow morning at 2 for 7 people', 7 being the trained 'number' in LUIS, the current TryFindEntity extension was pulling back '2', which was already considered part of the datetime entity

* added unit tests and correctet and updated logic to only consider an overlap if start and end index are within another entity recommendation
  • Loading branch information
gtewksbury authored and Tom Laird-McConnell committed Jun 29, 2018
1 parent 699d68f commit 3f6da33
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 1 deletion.
11 changes: 10 additions & 1 deletion CSharp/Library/Microsoft.Bot.Builder/Luis/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,16 @@ public static partial class Extensions
/// <returns>True if the entity was found, false otherwise.</returns>
public static bool TryFindEntity(this LuisResult result, string type, out EntityRecommendation entity)
{
entity = result.Entities?.FirstOrDefault(e => e.Type == type);
Func<EntityRecommendation, IList<EntityRecommendation>, bool> doesNotOverlapRange = (current, recommendations) =>
{
return !recommendations.Where(r => current != r)
.Any(r => r.StartIndex.HasValue && r.EndIndex.HasValue && current.StartIndex.HasValue &&
r.StartIndex.Value <= current.StartIndex.Value && r.EndIndex.Value >= current.EndIndex.Value);
};


// find the recommended entity that does not overlap start and end ranges with other result entities
entity = result.Entities?.Where(e => e.Type == type && doesNotOverlapRange(e, result.Entities)).FirstOrDefault();
return entity != null;
}

Expand Down
90 changes: 90 additions & 0 deletions CSharp/Tests/Microsoft.Bot.Builder.Tests/LuisTryFindEntityTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using Microsoft.Bot.Builder.Luis.Models;
using System.Collections.Generic;
using Microsoft.Bot.Builder.Luis;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Bot.Builder.Tests
{
[TestClass]
public class LuisTryFindEntityTests
{

[TestMethod]
public void Luis_TryFindEntity_Date_And_Multiple_Numbers_Where_One_Number_Overlaps()
{
// assemble

var recommendations = new List<EntityRecommendation>
{
new EntityRecommendation { Type = "builtin.datetimeV2.time", Entity = "10 pm", StartIndex=25, EndIndex=30},
new EntityRecommendation { Type = "builtin.number", Entity = "10", StartIndex=25, EndIndex=27},
new EntityRecommendation { Type = "builtin.number", Entity = "8", StartIndex=35, EndIndex=36}
};

var result = new LuisResult("make me a reservation at 10 pm for 8 people", recommendations);

// act

EntityRecommendation recommendation;
result.TryFindEntity("builtin.number", out recommendation);

// assert

Assert.IsNotNull(recommendation,"entity recommendation not found");
Assert.AreEqual("8", recommendation.Entity, "wrong entity recommendation selected"); // it should not select 10 since that overlaps with the datetime entity
}

[TestMethod]
public void Luis_TryFindEntity_Date_And_One_Number_Where_One_Number_Overlaps()
{
// assemble

var recommendations = new List<EntityRecommendation>
{
new EntityRecommendation { Type = "builtin.number", Entity = "10", StartIndex=25, EndIndex=27}, // it should not consider this a number since if overlaps with the datetime entity
new EntityRecommendation { Type = "builtin.datetimeV2.time", Entity = "10 pm", StartIndex=25, EndIndex=30}
};

var result = new LuisResult("make me a reservation at 10 pm", recommendations);

// act

EntityRecommendation numberRecommendation;
result.TryFindEntity("builtin.number", out numberRecommendation);

EntityRecommendation timeRecommendation;
result.TryFindEntity("builtin.datetimeV2.time", out timeRecommendation);


// assert

Assert.IsNotNull(timeRecommendation, "time entity recommendation not found");
Assert.IsNull(numberRecommendation, "number recommendation should be null as it falls within the datetime range");
Assert.AreEqual("10 pm", timeRecommendation.Entity, "wrong entity recommendation selected");
}

[TestMethod]
public void Luis_TryFindEntity_Find_Number_No_Overlaps()
{
// assemble

var recommendations = new List<EntityRecommendation>
{
new EntityRecommendation { Type = "builtin.number", Entity = "8", StartIndex=26, EndIndex=27},
};

var result = new LuisResult("make me a reservation for 8 people", recommendations);

// act

EntityRecommendation numberRecommendation;
result.TryFindEntity("builtin.number", out numberRecommendation);


// assert

Assert.IsNotNull(numberRecommendation, "number recommendation not found");
Assert.AreEqual("8", numberRecommendation.Entity, "wrong entity recommendation selected");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
<Compile Include="DialogTaskManagerTests.cs" />
<Compile Include="DialogTaskTests.cs" />
<Compile Include="DialogTestBase.cs" />
<Compile Include="LuisTryFindEntityTests.cs" />
<Compile Include="FormTests.cs" />
<Compile Include="OrderedContractResolver.cs" />
<Compile Include="PromptRecognizerTests.cs" />
Expand Down

1 comment on commit 3f6da33

@JasonJShuler
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is quite problematic - it will now never return a resolution if a word is recognized as more than one entity. For example, we have a speed entity with one of the values being "3" or "three" or "medium". "3" is recognized as both the builtin number and our entity - but since this change TryFindEntity will never work.

Please sign in to comment.