diff --git a/libraries/bot-ai-luis-v3/pom.xml b/libraries/bot-ai-luis-v3/pom.xml index 7622682ee..9b96d30d7 100644 --- a/libraries/bot-ai-luis-v3/pom.xml +++ b/libraries/bot-ai-luis-v3/pom.xml @@ -62,6 +62,38 @@ com.microsoft.bot bot-applicationinsights + + com.microsoft.bot + bot-dialogs + + + com.squareup.okhttp3 + okhttp + 4.9.0 + + + org.json + json + 20190722 + + + com.squareup.okhttp3 + mockwebserver + 4.9.0 + test + + + org.junit.jupiter + junit-jupiter-params + 5.7.0 + test + + + org.mockito + mockito-junit-jupiter + 3.6.0 + test + diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/DynamicList.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/DynamicList.java new file mode 100644 index 000000000..2c54b76fe --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/DynamicList.java @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** + * Request Body element to use when passing Dynamic lists to the Luis Service call. + * + */ +public class DynamicList { + + /** + * Initializes a new instance of the DynamicList class. + */ + public DynamicList() { + } + + /** + * Initializes a new instance of the DynamicList class. + * @param entity Entity field. + * @param requestLists List Elements to use when querying Luis Service. + */ + public DynamicList(String entity, List requestLists) { + this.entity = entity; + this.list = requestLists; + } + + @JsonProperty(value = "listEntityName") + private String entity; + + @JsonProperty(value = "requestLists") + private List list; + + /** + * Gets the entity. + * @return Entity name. + */ + public String getEntity() { + return entity; + } + + /** + * Sets the entity name. + * @param entity entity name. + */ + public void setEntity(String entity) { + this.entity = entity; + } + + /** + * Gets the List. + * @return Element list of the Dynamic List. + */ + public List getList() { + return list; + } + + /** + * Sets the List. + * @param list Element list of the Dynamic List. + */ + public void setList(List list) { + this.list = list; + } + + /** + * Validate the object. + * @throws IllegalArgumentException on null or invalid values. + */ + public void validate() throws IllegalArgumentException { + // Required: ListEntityName, RequestLists + if (entity == null || list == null) { + throw new IllegalArgumentException("ExternalEntity requires an EntityName and EntityLength > 0"); + } + + for (ListElement e: list) { + e.validate(); + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/ExternalEntity.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/ExternalEntity.java new file mode 100644 index 000000000..b2bf28893 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/ExternalEntity.java @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +/** + * Request Body element to use when passing External Entities to the Luis Service call. + * + */ +public class ExternalEntity { + + /** + * Initializes a new instance of ExternalEntity. + */ + public ExternalEntity() { + } + + /** + * Initializes a new instance of ExternalEntity. + * @param entity name of the entity to extend. + * @param start start character index of the predicted entity. + * @param length length of the predicted entity. + * @param resolution supplied custom resolution to return as the entity's prediction. + */ + public ExternalEntity(String entity, int start, int length, JsonNode resolution) { + this.entity = entity; + this.start = start; + this.length = length; + this.resolution = resolution; + } + + @JsonProperty(value = "entityName") + private String entity; + + + @JsonProperty(value = "startIndex") + private int start; + + + @JsonProperty(value = "entityLength") + private int length = -1; + + @JsonProperty(value = "resolution") + private JsonNode resolution; + + /** + * Gets the start character index of the predicted entity. + * @return start character index of the predicted entity. + */ + public int getStart() { + return start; + } + + /** + * Sets the start character index of the predicted entity. + * @param start character index of the predicted entity. + */ + public void setStart(int start) { + this.start = start; + } + + /** + * Gets the name of the entity to extend. + * @return name of the entity to extend. + */ + public String getEntity() { + return entity; + } + + /** + * Sets the name of the entity to extend. + * @param entity name of the entity to extend. + */ + public void setEntity(String entity) { + this.entity = entity; + } + + /** + * Gets the length of the predicted entity. + * @return length of the predicted entity. + */ + public int getLength() { + return length; + } + + /** + * Sets the length of the predicted entity. + * @param length of the predicted entity. + */ + public void setLength(int length) { + this.length = length; + } + + /** + * Gets a user supplied custom resolution to return as the entity's prediction. + * @return custom resolution to return as the entity's prediction. + */ + public JsonNode getResolution() { + return resolution; + } + + /** + * Sets External entities to be recognized in query. + * @param resolution custom resolution to return as the entity's prediction. + */ + public void setResolution(JsonNode resolution) { + this.resolution = resolution; + } + + /** + * Validate the object. + * @throws IllegalArgumentException on null or invalid values + */ + public void validate() throws IllegalArgumentException { + if (entity == null || length == -1) { + throw new IllegalArgumentException("ExternalEntity requires an EntityName and EntityLength > 0"); + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/ListElement.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/ListElement.java new file mode 100644 index 000000000..efeaa4d62 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/ListElement.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * List Element for Dynamic Lists. + * + */ +public class ListElement { + + /** + * Initializes a new instance of the ListElement class. + */ + public ListElement() { + } + + /** + * Initializes a new instance of the ListElement class. + * @param canonicalForm The canonical form of the sub-list. + * @param synonyms The synonyms of the canonical form. + */ + public ListElement(String canonicalForm, List synonyms) { + this.canonicalForm = canonicalForm; + this.synonyms = synonyms; + } + + /** + * The canonical form of the sub-list. + */ + @JsonProperty(value = "canonicalForm") + private String canonicalForm; + + /** + * The synonyms of the canonical form. + */ + @JsonProperty(value = "synonyms") + @JsonInclude(JsonInclude.Include.NON_NULL) + private List synonyms; + + /** + * Gets the canonical form of the sub-list. + * @return String canonical form of the sub-list. + */ + public String getCanonicalForm() { + return canonicalForm; + } + + /** + * Sets the canonical form of the sub-list. + * @param canonicalForm the canonical form of the sub-list. + */ + public void setCanonicalForm(String canonicalForm) { + this.canonicalForm = canonicalForm; + } + + /** + * Gets the synonyms of the canonical form. + * @return the synonyms List of the canonical form. + */ + public List getSynonyms() { + return synonyms; + } + + /** + * Sets the synonyms of the canonical form. + * @param synonyms List of synonyms of the canonical form. + */ + public void setSynonyms(List synonyms) { + this.synonyms = synonyms; + } + + /** + * Validate the object. + * @throws IllegalArgumentException if canonicalForm is null. + */ + public void validate() throws IllegalArgumentException { + if (canonicalForm == null) { + throw new IllegalArgumentException("RequestList requires CanonicalForm to be defined."); + } + } + +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisApplication.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisApplication.java new file mode 100644 index 000000000..b5afbfd89 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisApplication.java @@ -0,0 +1,228 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URIBuilder; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.UUID; + +/** + * Luis Application representation with information necessary to query the specific Luis Application. + * + */ +public class LuisApplication { + + /** + * Luis application ID. + */ + private String applicationId; + + /** + * Luis subscription or endpoint key. + */ + private String endpointKey; + + /** + * Luis subscription or endpoint key. + */ + private String endpoint; + + /** + * Luis endpoint like https://westus.api.cognitive.microsoft.com. + */ + public LuisApplication() { + } + + /** + * Initializes a new instance of the Luis Application class. + * @param applicationId Luis Application ID to query + * @param endpointKey LUIS subscription or endpoint key. + * @param endpoint LUIS endpoint to use like https://westus.api.cognitive.microsoft.com + */ + public LuisApplication( + String applicationId, + String endpointKey, + String endpoint) { + setLuisApplication( + applicationId, + endpointKey, + endpoint); + } + + /** + * Initializes a new instance of the Luis Application class. + * @param applicationEndpoint LUIS application query endpoint containing subscription key + * and application id as part of the url. + */ + public LuisApplication( + String applicationEndpoint) { + parse(applicationEndpoint); + } + + /** + * Sets Luis application ID to query. + * @param applicationId Luis application ID to query. + */ + public void setApplicationId(String applicationId) { + this.applicationId = applicationId; + } + + /** + * Gets Luis application ID. + * @return applicationId. + */ + public String getApplicationId() { + return applicationId; + } + + /** + * Sets the LUIS subscription or endpoint key. + * @param endpointKey LUIS subscription or endpoint key. + */ + public void setEndpointKey(String endpointKey) { + this.endpointKey = endpointKey; + } + + /** + * Gets the LUIS subscription or endpoint key. + * @return endpointKey. + */ + public String getEndpointKey() { + return endpointKey; + } + + /** + * Sets Luis endpoint like https://westus.api.cognitive.microsoft.com. + * @param endpoint endpoint like https://westus.api.cognitive.microsoft.com. + */ + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + /** + * Gets the LUIS endpoint where application is hosted. + * @return endpoint. + */ + public String getEndpoint() { + return endpoint; + } + + /** + * Helper method to set and validate Luis arguments passed. + */ + private void setLuisApplication( + String applicationId, + String endpointKey, + String endpoint) { + + if (!isValidUUID(applicationId)) { + throw new IllegalArgumentException(String.format("%s is not a valid LUIS application id.", applicationId)); + } + + + if (!isValidUUID(endpointKey)) { + throw new IllegalArgumentException(String.format("%s is not a valid LUIS subscription key.", endpointKey)); + } + + if (endpoint == null || endpoint.isEmpty()) { + endpoint = "https://westus.api.cognitive.microsoft.com"; + } + + if (!isValidURL(endpoint)) { + throw new IllegalArgumentException(String.format("%s is not a valid LUIS endpoint.", endpoint)); + } + + this.applicationId = applicationId; + this.endpointKey = endpointKey; + this.endpoint = endpoint; + } + + /** + * Helper method to parse validate and set Luis application members from the full application full endpoint. + */ + private void parse(String applicationEndpoint) { + String appId = ""; + try { + String[] segments = new URL(applicationEndpoint) + .getPath() + .split("/"); + for (int segment = 0; segment < segments.length - 1; segment++) { + if (segments[segment].equals("apps")) { + appId = segments[segment + 1].trim(); + break; + } + } + } catch (MalformedURLException e) { + throw new IllegalArgumentException( + String.format( + "Unable to create the LUIS endpoint with the given %s.", + applicationEndpoint + ) + ); + } + + + if (appId.isEmpty()) { + throw new IllegalArgumentException( + String.format( + "Could not find application Id in %s", + applicationEndpoint + ) + ); + } + + try { + + String endpointKeyParsed = new URIBuilder(applicationEndpoint) + .getQueryParams() + .stream() + .filter(param -> param.getName() + .equalsIgnoreCase("subscription-key")) + .map(NameValuePair::getValue) + .findFirst() + .orElse(""); + + String endpointPared = String.format( + "%s://%s", + new URL(applicationEndpoint).getProtocol(), + new URL(applicationEndpoint).toURI().getHost() + ); + + setLuisApplication(appId, endpointKeyParsed, endpointPared); + } catch (URISyntaxException | MalformedURLException e) { + throw new IllegalArgumentException( + String.format( + "Unable to create the LUIS endpoint with the given %s.", + applicationEndpoint + )); + } + + } + + private boolean isValidUUID(String uuid) { + try { + if (!uuid.contains("-")) { + uuid = uuid.replaceAll( + "(.{8})(.{4})(.{4})(.{4})(.+)", + "$1-$2-$3-$4-$5" + ); + } + + return UUID.fromString(uuid).toString().equals(uuid); + } catch (IllegalArgumentException e) { + return false; + } + } + + private boolean isValidURL(String uri) { + try { + return new URL(uri).toURI().isAbsolute(); + } catch (URISyntaxException | MalformedURLException exception) { + return false; + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizer.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizer.java new file mode 100644 index 000000000..c7a5d91cf --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizer.java @@ -0,0 +1,620 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.databind.JsonNode; +import com.microsoft.bot.builder.IntentScore; +import com.microsoft.bot.builder.RecognizerConvert; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.dialogs.DialogContext; +import com.microsoft.bot.schema.Activity; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * Luis Recognizer class to query the LUIS Service using the configuration set by the LuisRecognizeroptions. + * + */ +public class LuisRecognizer extends TelemetryRecognizer { + /** + * Luis Recognizer options to query the Luis Service. + */ + private LuisRecognizerOptions luisRecognizerOptions; + + /** + * Initializes a new instance of the Luis Recognizer . + * @param recognizerOptions Luis Recognizer options to use when calling th LUIS Service. + */ + public LuisRecognizer(LuisRecognizerOptions recognizerOptions) { + this.luisRecognizerOptions = recognizerOptions; + this.setLogPersonalInformation(recognizerOptions.isLogPersonalInformation()); + this.setTelemetryClient(recognizerOptions.getTelemetryClient()); + } + + /** + * Returns the name of the top scoring intent from a set of LUIS results. + * @param results The Recognizer Result with the list of Intents to filter. + * Defaults to a value of "None" and a min score value of `0.0` + * @return The top scoring intent name. + */ + public static String topIntent( + RecognizerResult results) { + return topIntent(results, "None"); + } + + /** + * Returns the name of the top scoring intent from a set of LUIS results. + * @param results The Recognizer Result with the list of Intents to filter + * @param defaultIntent Intent name to return should a top intent be found. + * Defaults to a value of "None" and a min score value of `0.0` + * @return The top scoring intent name. + */ + public static String topIntent( + RecognizerResult results, + String defaultIntent) { + return topIntent(results, defaultIntent, 0.0); + } + + /** + * Returns the name of the top scoring intent from a set of LUIS results. + * @param results The Recognizer Result with the list of Intents to filter. + * @param minScore Minimum score needed for an intent to be considered as a top intent. + * @return The top scoring intent name. + */ + public static String topIntent( + RecognizerResult results, + double minScore) { + return topIntent(results, "None", minScore); + } + + /** + * Returns the name of the top scoring intent from a set of LUIS results. + * @param results The Recognizer Result with the list of Intents to filter + * @param defaultIntent Intent name to return should a top intent be found. Defaults to a value of "None + * @param minScore Minimum score needed for an intent to be considered as a top intent. + * @return The top scoring intent name. + */ + public static String topIntent( + RecognizerResult results, + String defaultIntent, + double minScore) { + if (results == null) { + throw new IllegalArgumentException("RecognizerResult"); + } + + defaultIntent = defaultIntent == null || defaultIntent.equals("") ? "None" : defaultIntent; + + String topIntent = null; + double topScore = -1.0; + if (!results.getIntents().isEmpty()) { + for (Map.Entry intent : results.getIntents().entrySet()) { + + double score = intent.getValue().getScore(); + if (score > topScore && score >= minScore) { + topIntent = intent.getKey(); + topScore = score; + } + } + } + + return topIntent != null && !topIntent.equals("") ? topIntent : defaultIntent; + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + @Override + public CompletableFuture recognize( + TurnContext turnContext) { + return recognizeInternal( + turnContext, + null, + null, + null); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity) { + return recognizeInternal( + dialogContext, + activity, + null, + null, + null); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + TurnContext turnContext, + Class c) { + return recognizeInternal( + turnContext, + null, + null, + null) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param Type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + Class c) { + return recognizeInternal( + dialogContext, + activity, + null, + null, + null) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + @Override + public CompletableFuture recognize( + TurnContext turnContext, + Map telemetryProperties, + Map telemetryMetrics) { + return recognizeInternal( + turnContext, + null, + telemetryProperties, + telemetryMetrics); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + Map telemetryProperties, + Map telemetryMetrics) { + return recognizeInternal( + dialogContext, + activity, + null, + telemetryProperties, + telemetryMetrics); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @param Type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + TurnContext turnContext, + Map telemetryProperties, + Map telemetryMetrics, + Class c) { + return recognizeInternal( + turnContext, + null, + telemetryProperties, + telemetryMetrics) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @param Type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + Map telemetryProperties, + Map telemetryMetrics, + Class c) { + return recognizeInternal( + dialogContext, + activity, + null, + telemetryProperties, + telemetryMetrics) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param recognizerOptions A LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + TurnContext turnContext, + LuisRecognizerOptions recognizerOptions) { + return recognizeInternal( + turnContext, + recognizerOptions, + null, + null); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param recognizerOptions A LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + LuisRecognizerOptions recognizerOptions) { + return recognizeInternal( + dialogContext, + activity, + recognizerOptions, + null, + null); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param recognizerOptions A LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @param type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + TurnContext turnContext, + LuisRecognizerOptions recognizerOptions, + Class c) { + return recognizeInternal( + turnContext, + recognizerOptions, + null, + null) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param recognizerOptions A LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @param Type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + LuisRecognizerOptions recognizerOptions, + Class c) { + return recognizeInternal( + dialogContext, + activity, + recognizerOptions, + null, + null) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param recognizerOptions LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + TurnContext turnContext, + LuisRecognizerOptions recognizerOptions, + Map telemetryProperties, + Map telemetryMetrics) { + return recognizeInternal( + turnContext, + recognizerOptions, + telemetryProperties, + telemetryMetrics); + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param recognizerOptions A LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + LuisRecognizerOptions recognizerOptions, + Map telemetryProperties, + Map telemetryMetrics) { + return recognizeInternal( + dialogContext, + activity, + recognizerOptions, + telemetryProperties, + telemetryMetrics); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param recognizerOptions A LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @param Type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + TurnContext turnContext, + LuisRecognizerOptions recognizerOptions, + Map telemetryProperties, + Map telemetryMetrics, + Class c) { + return recognizeInternal( + turnContext, + recognizerOptions, + telemetryProperties, + telemetryMetrics) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Runs an utterance through a recognizer and returns a strongly-typed recognizer result. + * @param dialogContext Context object containing information for a single turn of conversation with a user. + * @param activity Activity to recognize. + * @param recognizerOptions LuisRecognizerOptions instance to be used by the call. This parameter overrides the + * default LuisRecognizerOptions passed in the constructor. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @param Type of result. + * @param c RecognizerConvert implemented class to convert the Recognizer Result into. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + LuisRecognizerOptions recognizerOptions, + Map telemetryProperties, + Map telemetryMetrics, + Class c) { + return recognizeInternal( + dialogContext, + activity, + recognizerOptions, + telemetryProperties, + telemetryMetrics) + .thenApply(recognizerResult -> convertRecognizerResult(recognizerResult, c)); + } + + /** + * Invoked prior to a LuisResult being logged. + * @param recognizerResult The Luis Results for the call. + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + */ + public void onRecognizerResult( + RecognizerResult recognizerResult, + TurnContext turnContext, + Map telemetryProperties, + Map telemetryMetrics) { + Map properties = fillLuisEventPropertiesAsync( + recognizerResult, + turnContext, + telemetryProperties); + // Track the event + this.getTelemetryClient().trackEvent( + LuisTelemetryConstants.LUIS_RESULT, + properties, + telemetryMetrics); + } + + private Map fillLuisEventPropertiesAsync( + RecognizerResult recognizerResult, + TurnContext turnContext, + Map telemetryProperties) { + + Map sortedIntents = sortIntents(recognizerResult); + ArrayList topTwoIntents = new ArrayList<>(); + Iterator> iterator = sortedIntents.entrySet().iterator(); + int intentCounter = 0; + while (iterator.hasNext() + && intentCounter < 2) { + intentCounter++; + Map.Entry intent = iterator.next(); + topTwoIntents.add(intent.getKey()); + } + + // Add the intent score and conversation id properties + Map properties = new HashMap<>(); + properties.put( + LuisTelemetryConstants.APPLICATION_ID_PROPERTY, + luisRecognizerOptions.getApplication().getApplicationId()); + properties.put( + LuisTelemetryConstants.INTENT_PROPERTY, + topTwoIntents.size() > 0 ? topTwoIntents.get(0) : ""); + properties.put( + LuisTelemetryConstants.INTENT_SCORE_PROPERTY, + topTwoIntents.size() > 0 + ? "" + recognizerResult.getIntents().get(topTwoIntents.get(0)).getScore() + : "0.00"); + properties.put( + LuisTelemetryConstants.INTENT_2_PROPERTY, + topTwoIntents.size() > 1 ? topTwoIntents.get(1) : ""); + properties.put( + LuisTelemetryConstants.INTENT_SCORE_2_PROPERTY, + topTwoIntents.size() > 1 + ? "" + recognizerResult.getIntents().get(topTwoIntents.get(1)).getScore() + : "0.00"); + properties.put( + LuisTelemetryConstants.FROM_ID_PROPERTY, turnContext.getActivity().getFrom().getId()); + + if (recognizerResult.getProperties().containsKey("sentiment")) { + JsonNode sentiment = recognizerResult.getProperties().get("sentiment"); + if (sentiment.has("label")) { + properties.put( + LuisTelemetryConstants.SENTIMENT_LABEL_PROPERTY, + sentiment.get("label").textValue()); + } + + if (sentiment.has("score")) { + properties.put( + LuisTelemetryConstants.SENTIMENT_SCORE_PROPERTY, + sentiment.get("score").textValue()); + } + } + + properties.put( + LuisTelemetryConstants.ENTITIES_PROPERTY, + recognizerResult.getEntities().toString()); + + // Use the LogPersonalInformation flag to toggle logging PII data, text is a common example + if (isLogPersonalInformation() + && turnContext.getActivity().getText() != null + && !turnContext.getActivity().getText().equals("")) { + properties.put( + LuisTelemetryConstants.QUESTION_PROPERTY, + turnContext.getActivity().getText()); + } + + // Additional Properties can override "stock" properties. + if (telemetryProperties == null) { + telemetryProperties = new HashMap<>(); + } + + properties.putAll(telemetryProperties); + + return properties; + } + + private T convertRecognizerResult( + RecognizerResult recognizerResult, + Class clazz) { + T result; + try { + result = clazz.newInstance(); + result.convert(recognizerResult); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException( + String.format("Exception thrown when converting " + + "Recgonizer Result to strongly typed: %s : %s", + clazz.getName(), + e.getMessage())); + } + return result; + } + + /** + * Returns a RecognizerResult object. This method will call the internal recognize implementation of the + * Luis Recognizer Options. + */ + private CompletableFuture recognizeInternal( + TurnContext turnContext, + LuisRecognizerOptions options, + Map telemetryProperties, + Map telemetryMetrics) { + LuisRecognizerOptions predictionOptionsToRun = options == null ? luisRecognizerOptions : options; + return predictionOptionsToRun.recognizeInternal(turnContext) + .thenApply(recognizerResult -> { + onRecognizerResult( + recognizerResult, + turnContext, + telemetryProperties, + telemetryMetrics); + return recognizerResult; + }); + } + + /** + * Returns a RecognizerResult object. This method will call the internal recognize implementation of the + * Luis Recognizer Options. + */ + private CompletableFuture recognizeInternal( + DialogContext dialogContext, + Activity activity, + LuisRecognizerOptions options, + Map telemetryProperties, + Map telemetryMetrics) { + LuisRecognizerOptions predictionOptionsToRun = options == null ? luisRecognizerOptions : options; + return predictionOptionsToRun.recognizeInternal( + dialogContext, + activity) + .thenApply(recognizerResult -> { + onRecognizerResult( + recognizerResult, + dialogContext.getContext(), + telemetryProperties, + telemetryMetrics); + return recognizerResult; + }); + } + + private Map sortIntents(RecognizerResult recognizerResult) { + Map sortedIntents = new LinkedHashMap<>(); + recognizerResult.getIntents().entrySet() + .stream() + .sorted(Map.Entry.comparingByValue(Comparator.comparingDouble(IntentScore::getScore).reversed())) + .forEachOrdered(x -> sortedIntents.put(x.getKey(), x.getValue())); + return sortedIntents; + } +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizerOptions.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizerOptions.java new file mode 100644 index 000000000..c1cb374fc --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizerOptions.java @@ -0,0 +1,143 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.microsoft.bot.builder.BotTelemetryClient; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.dialogs.DialogContext; +import com.microsoft.bot.schema.Activity; +import java.util.concurrent.CompletableFuture; + +/** + * Abstract class to enforce the Strategy pattern consumed by the Luis Recognizer through the options selected. + * + */ +public abstract class LuisRecognizerOptions { + + /** + * Initializes an instance of the LuisRecognizerOptions implementation. + * @param application An instance of LuisApplication". + */ + protected LuisRecognizerOptions(LuisApplication application) { + if (application == null) { + throw new IllegalArgumentException("Luis Application may not be null"); + } + this.application = application; + } + + /** + * Luis Application instance. + */ + private LuisApplication application; + + /** + * Bot Telemetry Client instance. + */ + private BotTelemetryClient telemetryClient = null; + + /** + * Controls if personal information should be sent as telemetry. + */ + private boolean logPersonalInformation = false; + + /** + * Controls if full results from the LUIS API should be returned with the recognizer result. + */ + private boolean includeAPIResults = false; + + /** + * Gets the Luis Application instance. + * + * @return The Luis Application instance used with this Options. + */ + public LuisApplication getApplication() { + return application; + } + + /** + * Sets the Luis Application. + * + * @param application A Luis Application instance which sets the Luis specifics to work with + */ + public void setApplication( + LuisApplication application) { + this.application = application; + } + + /** + * Gets the currently configured Bot Telemetry Client that logs the LuisResult event. + * + * @return The Bot Telemetry Client. + */ + public BotTelemetryClient getTelemetryClient() { + return telemetryClient; + } + + /** + * Sets the Bot Telemetry Client to log telemetry with. + * + * @param telemetryClient A Bot Telemetry Client instance + */ + public void setTelemetryClient( + BotTelemetryClient telemetryClient) { + this.telemetryClient = telemetryClient; + } + + /** + * Indicates if personal information should be sent as telemetry. + * @return value boolean value to control personal information logging. + */ + public boolean isLogPersonalInformation() { + return logPersonalInformation; + } + + /** + * Indicates if personal information should be sent as telemetry. + * @param logPersonalInformation to set personal information logging preference. + */ + public void setLogPersonalInformation( + boolean logPersonalInformation) { + this.logPersonalInformation = logPersonalInformation; + } + + /** + * Indicates if full results from the LUIS API should be returned with the recognizer result. + * @return boolean value showing preference on LUIS API full response added to recognizer result. + */ + public boolean isIncludeAPIResults() { + return includeAPIResults; + } + + /** + * Indicates if full results from the LUIS API should be returned with the recognizer result. + * @param includeAPIResults to set full Luis API response to be added to the recognizer result. + */ + public void setIncludeAPIResults( + boolean includeAPIResults) { + this.includeAPIResults = includeAPIResults; + } + + /** + * Implementation of the Luis API http call and result processing. + * This is intended to follow a Strategy pattern and + * should only be consumed through the LuisRecognizer class. + * @param turnContext used to extract the text utterance to be sent to Luis. + * @return Recognizer Result populated by the Luis response. + */ + abstract CompletableFuture recognizeInternal( + TurnContext turnContext); + + /** + * Implementation of the Luis API http call and result processing. + * This is intended to follow a Strategy pattern and + * should only be consumed through the LuisRecognizer class. + * @param context Dialog Context to extract turn context. + * @param activity to extract the text utterance to be sent to Luis. + * @return Recognizer Result populated by the Luis response. + */ + abstract CompletableFuture recognizeInternal( + DialogContext context, + Activity activity); +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizerOptionsV3.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizerOptionsV3.java new file mode 100644 index 000000000..1a870fc88 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisRecognizerOptionsV3.java @@ -0,0 +1,769 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.microsoft.bot.builder.IntentScore; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.dialogs.DialogContext; +import com.microsoft.bot.dialogs.Recognizer; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ResourceResponse; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +/** + * Luis Recognizer Options for V3 LUIS Runtime. + * + */ +public class LuisRecognizerOptionsV3 extends LuisRecognizerOptions { + private final HashSet dateSubtypes = new HashSet<>( + Arrays.asList( + "date", + "daterange", + "datetime", + "datetimerange", + "duration", + "set", + "time", + "timerange" + )); + + private final HashSet geographySubtypes = new HashSet<>( + Arrays.asList( + "poi", + "city", + "countryRegion", + "continent", + "state" + )); + + private final String metadataKey = "$instance"; + + /** + * DatetimeV2 offset. The format for the datetimeReference is ISO 8601. + */ + private String dateTimeReference = null; + + /** + * Dynamic lists used to recognize entities for a particular query. + */ + private List dynamicLists = null; + + /** + * External entities recognized in query. + */ + private List externalEntities = null; + + /** + * External entity recognizer to recognize external entities to pass to LUIS. + */ + private Recognizer externalEntityRecognizer = null; + + /** + * Value indicating whether all intents come back or only the top one. True for returning all intents. + */ + private boolean includeAllIntents = false; + + /** + * Value indicating whether or not instance data should be included in response. + */ + private boolean includeInstanceData = false; + + /** + * Value indicating whether queries should be logged in LUIS. If queries should be logged in LUIS in order to help + * build better models through active learning + */ + private boolean log = true; + + /** + * Value indicating whether external entities should override other means of recognizing entities. True if external + * entities should be preferred to the results from LUIS models + */ + private boolean preferExternalEntities = true; + + /** + * The LUIS slot to use for the application. By default this uses the production slot. You can find other standard + * slots in LuisSlot. If you specify a Version, then a private version of the application is used instead of a slot. + */ + private String slot = LuisSlot.PRODUCTION; + + /** + * The specific version of the application to access. LUIS supports versions and this is the version to use instead + * of a slot. If this is specified, then the Slot is ignored. + */ + private String version = null; + + /** + * The HttpClient instance to use for http calls against the LUIS endpoint. + */ + private OkHttpClient httpClient = new OkHttpClient(); + + /** + * The value type for a LUIS trace activity. + */ + public static final String LUIS_TRACE_TYPE = "https://www.luis.ai/schemas/trace"; + + /** + * The context label for a LUIS trace activity. + */ + public static final String LUIS_TRACE_LABEL = "LuisV3 Trace"; + + /** + * Gets External entity recognizer to recognize external entities to pass to LUIS. + * @return externalEntityRecognizer + */ + public Recognizer getExternalEntityRecognizer() { + return externalEntityRecognizer; + } + + /** + * Sets External entity recognizer to recognize external entities to pass to LUIS. + * @param externalEntityRecognizer External Recognizer instance. + */ + public void setExternalEntityRecognizer(Recognizer externalEntityRecognizer) { + this.externalEntityRecognizer = externalEntityRecognizer; + } + + /** + * Gets indicating whether all intents come back or only the top one. True for returning all intents. + * @return True for returning all intents. + */ + public boolean isIncludeAllIntents() { + return includeAllIntents; + } + + /** + * Sets indicating whether all intents come back or only the top one. + * @param includeAllIntents True for returning all intents. + */ + public void setIncludeAllIntents(boolean includeAllIntents) { + this.includeAllIntents = includeAllIntents; + } + + /** + * Gets value indicating whether or not instance data should be included in response. + * @return True if instance data should be included in response. + */ + public boolean isIncludeInstanceData() { + return includeInstanceData; + } + + /** + * Sets value indicating whether or not instance data should be included in response. + * @param includeInstanceData True if instance data should be included in response. + */ + public void setIncludeInstanceData(boolean includeInstanceData) { + this.includeInstanceData = includeInstanceData; + } + + /** + * Value indicating whether queries should be logged in LUIS. If queries should be logged in LUIS in order to help + * build better models through active learning + * @return True if queries should be logged in LUIS. + */ + public boolean isLog() { + return log; + } + + /** + * Value indicating whether queries should be logged in LUIS. If queries should be logged in LUIS in order to help + * build better models through active learning. + * @param log True if queries should be logged in LUIS. + */ + public void setLog(boolean log) { + this.log = log; + } + + /** + * Returns Dynamic lists used to recognize entities for a particular query. + * @return Dynamic lists used to recognize entities for a particular query + */ + public List getDynamicLists() { + return dynamicLists; + } + + /** + * Sets Dynamic lists used to recognize entities for a particular query. + * @param dynamicLists to recognize entities for a particular query. + */ + public void setDynamicLists(List dynamicLists) { + this.dynamicLists = dynamicLists; + } + + /** + * Gets External entities to be recognized in query. + * @return External entities to be recognized in query. + */ + public List getExternalEntities() { + return externalEntities; + } + + /** + * Sets External entities to be recognized in query. + * @param externalEntities External entities to be recognized in query. + */ + public void setExternalEntities(List externalEntities) { + this.externalEntities = externalEntities; + } + + /** + * Gets value indicating whether external entities should override other means of recognizing entities. + * @return True if external entities should be preferred to the results from LUIS models. + */ + public boolean isPreferExternalEntities() { + return preferExternalEntities; + } + + /** + * Sets value indicating whether external entities should override other means of recognizing entities. + * @param preferExternalEntities True if external entities should be preferred to the results from LUIS models. + */ + public void setPreferExternalEntities(boolean preferExternalEntities) { + this.preferExternalEntities = preferExternalEntities; + } + + /** + * Gets datetimeV2 offset. The format for the datetimeReference is ISO 8601. + * @return The format for the datetimeReference in ISO 8601. + */ + public String getDateTimeReference() { + return dateTimeReference; + } + + /** + * Sets datetimeV2 offset. + * @param dateTimeReference The format for the datetimeReference is ISO 8601. + */ + public void setDateTimeReference(String dateTimeReference) { + this.dateTimeReference = dateTimeReference; + } + + /** + * Gets the LUIS slot to use for the application. By default this uses the production slot. + * You can find other standard slots in LuisSlot. If you specify a Version, + * then a private version of the application is used instead of a slot. + * @return LuisSlot constant. + */ + public String getSlot() { + return slot; + } + + /** + * Sets the LUIS slot to use for the application. By default this uses the production slot. + * You can find other standard slots in LuisSlot. If you specify a Version, + * then a private version of the application is used instead of a slot. + * @param slot LuisSlot value to use. + */ + public void setSlot(String slot) { + this.slot = slot; + } + + /** + * Gets the specific version of the application to access. + * LUIS supports versions and this is the version to use instead of a slot. + * If this is specified, then the Slot is ignored. + * @return Luis application version to Query. + */ + public String getVersion() { + return version; + } + + /** + * Sets the specific version of the application to access. + * LUIS supports versions and this is the version to use instead of a slot. + * @param version Luis Application version. If this is specified, then the Slot is ignored. + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Gets whether the http client. + * @return OkHttpClient used to query the Luis Service. + */ + public OkHttpClient getHttpClient() { + return httpClient; + } + + /** + * Sets the http client. + * @param httpClient to use for Luis Service http calls. + */ + public void setHttpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + } + + /** + * Initializes a new instance of the LuisRecognizerOptionsV3. + * @param application Luis Application instance to query. + */ + public LuisRecognizerOptionsV3(LuisApplication application) { + super(application); + } + + /** + * Internal implementation of the http request to the LUIS service and parsing of the response to a + * Recognizer Result instance. + * @param dialogContext Context Object. + * @param activity Activity object to extract the utterance. + */ + @Override + CompletableFuture recognizeInternal( + DialogContext dialogContext, + Activity activity + ) { + if (externalEntityRecognizer == null) { + return recognizeInternal( + dialogContext.getContext(), + activity.getText()); + } + + // call external entity recognizer + List originalExternalEntities = externalEntities; + return externalEntityRecognizer + .recognize(dialogContext, activity) + .thenCompose( + matches -> { + if (matches.getEntities() == null + || matches.getEntities().toString().equals("{}")) { + return recognizeInternal( + dialogContext.getContext(), + activity.getText()); + } + + List recognizerExternalEntities = new ArrayList<>(); + JsonNode entities = matches.getEntities(); + JsonNode instance = entities.get("$instance"); + + if (instance == null) { + return recognizeInternal( + dialogContext.getContext(), + activity.getText()); + } + + Iterator> instanceEntitiesIterator = instance.fields(); + + while (instanceEntitiesIterator.hasNext()) { + Map.Entry property = instanceEntitiesIterator.next(); + + if (property.getKey().equals("text") + || property.getKey().equals("$instance")) { + continue; + } + + ArrayNode instances = (ArrayNode) instance.get(property.getKey()); + ArrayNode values = (ArrayNode) property.getValue(); + + if (instances == null + || values == null + || instances.size() != values.size()) { + continue; + } + + for (JsonNode childInstance : values) { + if (childInstance != null + && childInstance.has("startIndex") + && childInstance.has("endIndex")) { + int start = childInstance.get("startIndex").asInt(); + int end = childInstance.get("endIndex").asInt(); + recognizerExternalEntities.add(new ExternalEntity( + property.getKey(), + start, + end - start, + property.getValue())); + } + } + recognizerExternalEntities.addAll( + originalExternalEntities == null + ? new ArrayList<>() + : originalExternalEntities + ); + externalEntities = recognizerExternalEntities; + } + + return recognizeInternal(dialogContext.getContext(), activity.getText()) + .thenApply(recognizerResult -> { + externalEntities = originalExternalEntities; + return recognizerResult; + }); + }); + } + + /** + * Internal implementation of the http request to the LUIS service and parsing of the response to a + * Recognizer Result instance. + * @param turnContext Context Object. + */ + @Override + CompletableFuture recognizeInternal( + TurnContext turnContext) { + return recognizeInternal( + turnContext, + turnContext.getActivity().getText()); + } + + private Request buildRequest(RequestBody body) { + StringBuilder path = new StringBuilder(getApplication().getEndpoint()); + path.append(String.format( + "/luis/prediction/v3.0/apps/%s", + getApplication().getApplicationId())); + + if (version == null) { + path.append(String.format("/slots/%s/predict", slot)); + } else { + path.append(String.format("/versions/%s/predict", version)); + } + + HttpUrl.Builder httpBuilder = HttpUrl.parse(path.toString()).newBuilder(); + + httpBuilder.addQueryParameter("verbose", Boolean.toString(includeInstanceData)); + httpBuilder.addQueryParameter("log", Boolean.toString(log)); + httpBuilder.addQueryParameter("show-all-intents", Boolean.toString(includeAllIntents)); + + Request.Builder requestBuilder = new Request.Builder() + .url(httpBuilder.build()) + .addHeader("Ocp-Apim-Subscription-Key", getApplication().getEndpointKey()).post(body); + return requestBuilder.build(); + } + + private RequestBody buildRequestBody(String utterance) throws JsonProcessingException { + + ObjectMapper mapper = new ObjectMapper(); + ObjectNode content = JsonNodeFactory.instance.objectNode().put("query", utterance); + ObjectNode queryOptions = JsonNodeFactory.instance.objectNode().put( + "preferExternalEntities", + preferExternalEntities); + + if (dateTimeReference != null + && !dateTimeReference.isEmpty()) { + queryOptions.put( + "datetimeReference", + dateTimeReference); + } + + content.set("options", queryOptions); + + if (dynamicLists != null) { + content.set("dynamicLists", mapper.valueToTree(dynamicLists)); + } + + if (externalEntities != null) { + for (ExternalEntity entity : externalEntities) { + entity.validate(); + } + content.set("externalEntities", mapper.valueToTree(externalEntities)); + } + + String contentAsText = mapper.writeValueAsString(content); + return RequestBody.create(contentAsText, MediaType.parse("application/json; charset=utf-8")); + } + + private CompletableFuture recognizeInternal( + TurnContext turnContext, + String utterance) { + + RecognizerResult recognizerResult; + JsonNode luisResponse = null; + ObjectMapper mapper = new ObjectMapper(); + + if (utterance == null || utterance.isEmpty()) { + recognizerResult = new RecognizerResult() {{ + setText(utterance); + }}; + } else { + try { + Request request = buildRequest(buildRequestBody(utterance)); + Response response = httpClient.newCall(request).execute(); + luisResponse = mapper.readTree(response.body().string()); + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + luisResponse.toString()); + } + + } catch (IOException e) { + CompletableFuture exceptionResult = new CompletableFuture<>(); + exceptionResult.completeExceptionally(e); + return exceptionResult; + } + + JsonNode prediction = luisResponse.get("prediction"); + recognizerResult = new RecognizerResult(); + recognizerResult.setText(utterance); + if (prediction.get("alteredQuery") != null) { + recognizerResult.setAlteredText(prediction.get("alteredQuery").asText()); + } + + recognizerResult.setIntents(getIntents(prediction)); + recognizerResult.setEntities(getEntities(prediction)); + + addProperties(prediction, recognizerResult); + if (isIncludeAPIResults()) { + recognizerResult.getProperties().put("luisResult", luisResponse); + } + + if (includeInstanceData + && recognizerResult.getEntities().get(metadataKey) == null) { + ((ObjectNode) recognizerResult.getEntities()).putObject(metadataKey); + } + } + + return sendTraceActivity(recognizerResult, luisResponse, turnContext) + .thenApply(v -> recognizerResult); + + } + + private Map getIntents(JsonNode prediction) { + Map intents = new LinkedHashMap<>(); + + JsonNode intentsObject = prediction.get("intents"); + if (intentsObject == null) { + return intents; + } + + for (Iterator> it = intentsObject.fields(); it.hasNext();) { + Map.Entry intent = it.next(); + double score = intent.getValue() + .get("score") + .asDouble(); + String intentName = intent.getKey() + .replace(".", "_") + .replace(" ", "_"); + intents.put(intentName, new IntentScore() {{ + setScore(score); + }}); + } + + return intents; + } + + private String normalizeEntity(String entity) { + // Type::Role -> Role + String[] type = entity.split(":"); + return type[type.length - 1] + .replace(".", "_") + .replace(" ", "_"); + } + + private JsonNode getEntities(JsonNode prediction) { + if (prediction.get("entities") == null) { + return JsonNodeFactory.instance.objectNode(); + } + + return mapEntitiesRecursive(prediction.get("entities"), false); + } + + // Exact Port from C# + private JsonNode mapEntitiesRecursive( + JsonNode source, + boolean inInstance) { + JsonNode result = source; + if (!source.isArray() + && source.isObject()) { + ObjectNode nobj = JsonNodeFactory.instance.objectNode(); + // Fix datetime by reverting to simple timex + JsonNode obj = source; + JsonNode type = source.get("type"); + + if (!inInstance + && type != null + && dateSubtypes.contains(type.asText())) { + JsonNode timexs = obj.get("values"); + ArrayNode arr = JsonNodeFactory.instance.arrayNode(); + if (timexs != null) { + Set unique = new HashSet<>(); + + for (JsonNode elt: timexs) { + unique.add(elt.get("timex").textValue()); + } + + for (String timex : unique) { + arr.add(timex); + } + + nobj.set("timex", arr); + } + + nobj.set("type", type); + } else { + // Map or remove properties + Iterator> nodes = obj.fields(); + while (nodes.hasNext()) { + Map.Entry property = (Map.Entry) nodes.next(); + String name = normalizeEntity(property.getKey()); + boolean isArray = property.getValue().isArray(); + boolean isString = property.getValue().isTextual(); + boolean isInt = property.getValue().isInt(); + JsonNode val = mapEntitiesRecursive( + property.getValue(), + inInstance || name.equals(metadataKey)); + + if (name.equals("datetime") + && isArray) { + nobj.set("datetimeV1", val); + } else if (name.equals("datetimeV2") + && isArray) { + nobj.set("datetime", val); + } else if (inInstance) { + // Correct $instance issues + if (name.equals("length") && isInt) { + int value = property.getValue().intValue(); + if (obj.get("startIndex") != null) { + value += obj.get("startIndex").intValue(); + } + nobj.put("endIndex", value); + } else if (!((isInt && name.equals("modelTypeId")) || //NOPMD + (isString && name.equals("role")))) { //NOPMD + nobj.set(name, val); + } + } else { + // Correct non-$instance values + if (name.equals("unit") && isString) { + nobj.set("units", val); + } else { + nobj.set(name, val); + } + } + } + } + + result = nobj; + } else if (source.isArray()) { + JsonNode arr = source; + ArrayNode narr = JsonNodeFactory.instance.arrayNode(); + for (JsonNode elt : arr) { + // Check if element is geographyV2 + String isGeographyV2 = ""; + + Iterator> nodes = elt.fields(); + while (nodes.hasNext()) { + Map.Entry props = (Map.Entry) nodes.next(); + + if (props == null) { + break; + } + + if (props.getKey().contains("type") + && geographySubtypes.contains(props.getValue().textValue())) { + isGeographyV2 = props.getValue().textValue(); + break; + } + } + + if (!inInstance && !isGeographyV2.isEmpty()) { + ObjectNode geoEntity = JsonNodeFactory.instance.objectNode(); + nodes = elt.fields(); + while (nodes.hasNext()) { + Map.Entry tokenProp = (Map.Entry) nodes.next(); + + if (tokenProp.getKey().contains("value")) { + geoEntity.set("location", tokenProp.getValue()); + } + } + + geoEntity.put("type", isGeographyV2); + narr.add(geoEntity); + } else { + narr.add(mapEntitiesRecursive(elt, inInstance)); + } + } + result = narr; + } + + return result; + } + + private void addProperties( + JsonNode prediction, + RecognizerResult result) { + JsonNode sentiment = prediction.get("sentiment"); + if (sentiment != null) { + ObjectNode sentimentNode = JsonNodeFactory.instance.objectNode(); + sentimentNode.set("label", sentiment.get("label")); + sentimentNode.set("score", sentiment.get("score")); + result.getProperties().put("sentiment", sentimentNode); + } + } + + private CompletableFuture sendTraceActivity( + RecognizerResult recognizerResult, + JsonNode luisResponse, + TurnContext turnContext) { + ObjectMapper mapper = new ObjectMapper(); + try { + ObjectNode traceInfo = JsonNodeFactory.instance.objectNode(); + traceInfo.put( + "recognizerResult", + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(recognizerResult)); + traceInfo.set( + "luisResult", + luisResponse); + traceInfo.set( + "luisModel", + JsonNodeFactory.instance.objectNode() + .put("ModelId", + getApplication().getApplicationId())); + + ObjectNode luisOptions = JsonNodeFactory.instance.objectNode(); + luisOptions.put("includeAllIntents", includeAllIntents); + luisOptions.put("includeInstanceData", includeInstanceData); + luisOptions.put("log", log); + luisOptions.put("preferExternalEntities", preferExternalEntities); + luisOptions.put("dateTimeReference", dateTimeReference); + luisOptions.put("slot", slot); + luisOptions.put("version", version); + + + if (externalEntities != null) { + ArrayNode externalEntitiesNode = JsonNodeFactory.instance.arrayNode(); + for (ExternalEntity e : externalEntities) { + externalEntitiesNode.add(mapper.valueToTree(e)); + } + luisOptions.put("externalEntities", externalEntitiesNode); + } + + if (dynamicLists != null) { + ArrayNode dynamicListNode = JsonNodeFactory.instance.arrayNode(); + for (DynamicList e : dynamicLists) { + dynamicListNode.add(mapper.valueToTree(e)); + } + luisOptions.put("dynamicLists", dynamicListNode); + } + + traceInfo.set("luisOptions", luisOptions); + + return turnContext.sendActivity( + Activity.createTraceActivity( + "LuisRecognizer", + LUIS_TRACE_TYPE, + traceInfo, + LUIS_TRACE_LABEL)); + + } catch (IOException e) { + CompletableFuture exceptionResult = new CompletableFuture<>(); + exceptionResult.completeExceptionally(e); + return exceptionResult; + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisSlot.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisSlot.java new file mode 100644 index 000000000..6ab42ea68 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisSlot.java @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +/** + * Utility class to set the Luis endpoint Slot. + * + */ +public final class LuisSlot { + + //Not Called + private LuisSlot() { + + } + + /** + * Production slot on LUIS. + */ + public static final String PRODUCTION = "production"; + + /** + * Staging slot on LUIS. + */ + public static final String STAGING = "staging"; +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisTelemetryConstants.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisTelemetryConstants.java new file mode 100644 index 000000000..f3ae43e84 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/LuisTelemetryConstants.java @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +/** + * Utility class to set the telemetry values for the Luis Recognizer. + * + */ +public final class LuisTelemetryConstants { + + private LuisTelemetryConstants() { + + } + + /** + * The Key used when storing a LUIS Result in a custom event within telemetry. + */ + public static final String LUIS_RESULT = "LuisResult"; // Event name + + /** + * The Key used when storing a LUIS app ID in a custom event within telemetry. + */ + public static final String APPLICATION_ID_PROPERTY = "applicationId"; + + /** + * The Key used when storing a LUIS intent in a custom event within telemetry. + */ + public static final String INTENT_PROPERTY = "intent"; + + /** + * The Key used when storing a LUIS intent score in a custom event within telemetry. + */ + public static final String INTENT_SCORE_PROPERTY = "intentScore"; + + /** + * The Key used when storing a LUIS intent in a custom event within telemetry. + */ + public static final String INTENT_2_PROPERTY = "intent2"; + + /** + * The Key used when storing a LUIS intent score in a custom event within telemetry. + */ + public static final String INTENT_SCORE_2_PROPERTY = "intentScore2"; + + /** + * The Key used when storing LUIS entities in a custom event within telemetry. + */ + public static final String ENTITIES_PROPERTY = "entities"; + + /** + * The Key used when storing the LUIS query in a custom event within telemetry. + */ + public static final String QUESTION_PROPERTY = "question"; + + /** + * The Key used when storing an Activity ID in a custom event within telemetry. + */ + public static final String ACTIVITY_ID_PROPERTY = "activityId"; + + /** + * The Key used when storing a sentiment label in a custom event within telemetry. + */ + public static final String SENTIMENT_LABEL_PROPERTY = "sentimentLabel"; + + /** + * The Key used when storing a LUIS sentiment score in a custom event within telemetry. + */ + public static final String SENTIMENT_SCORE_PROPERTY = "sentimentScore"; + + /** + * The Key used when storing the FromId in a custom event within telemetry. + */ + public static final String FROM_ID_PROPERTY = "fromId"; +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/TelemetryRecognizer.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/TelemetryRecognizer.java new file mode 100644 index 000000000..9ea56fec3 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/TelemetryRecognizer.java @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.microsoft.bot.builder.BotTelemetryClient; +import com.microsoft.bot.builder.Recognizer; +import com.microsoft.bot.builder.RecognizerConvert; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.builder.TurnContext; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * Telemetry Recognizer to enforce controls and properties on telemetry logged. + * + */ +public abstract class TelemetryRecognizer implements Recognizer { + + private boolean logPersonalInformation; + + private BotTelemetryClient telemetryClient; + + /** + * Indicates if personal information should be sent as telemetry. + * @return value boolean value to control personal information logging. + */ + public boolean isLogPersonalInformation() { + return logPersonalInformation; + } + + /** + * Indicates if personal information should be sent as telemetry. + * @param logPersonalInformation to set personal information logging preference. + */ + protected void setLogPersonalInformation(boolean logPersonalInformation) { + this.logPersonalInformation = logPersonalInformation; + } + + /** + * Gets the currently configured Bot Telemetry Client that logs the LuisResult event. + * @return The Bot Telemetry Client. + */ + protected BotTelemetryClient getTelemetryClient() { + return telemetryClient; + } + + /** + * Sets the currently configured Bot Telemetry Client that logs the LuisResult event. + * @param telemetryClient Bot Telemetry Client. + */ + public void setTelemetryClient(BotTelemetryClient telemetryClient) { + this.telemetryClient = telemetryClient; + } + + /** + * Return results of the analysis (Suggested actions and intents). + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + abstract CompletableFuture recognize( + TurnContext turnContext, + Map telemetryProperties, + Map telemetryMetrics); + + /** + * Return results of the analysis (Suggested actions and intents). + * @param turnContext Context object containing information for a single turn of conversation with a user. + * @param telemetryProperties Additional properties to be logged to telemetry with the LuisResult event. + * @param telemetryMetrics Additional metrics to be logged to telemetry with the LuisResult event. + * @param Result type. + * @param c The recognition result type class + * @return The LUIS results of the analysis of the current message text in the current turn's context activity. + */ + abstract CompletableFuture recognize( + TurnContext turnContext, + Map telemetryProperties, + Map telemetryMetrics, + Class c); + +} diff --git a/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/package-info.java b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/package-info.java new file mode 100644 index 000000000..181eab803 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/main/java/com/microsoft/bot/ai/luis/package-info.java @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. + +/** + * This package contains the classes for Bot-AI-LUIS. + */ + +package com.microsoft.bot.ai.luis; diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisApplicationTests.java b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisApplicationTests.java new file mode 100644 index 000000000..c550451b9 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisApplicationTests.java @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class LuisApplicationTests { + String validUUID = "b31aeaf3-3511-495b-a07f-571fc873214b"; + String invalidUUID = "0000"; + String validEndpoint = "https://www.test.com"; + String invalidEndpoint = "www.test.com"; + + @Test + public void invalidSubscriptionKey() { + + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + LuisApplication lA = new LuisApplication( + validUUID, + invalidUUID, + validEndpoint); + }); + + String expectedMessage = String.format("%s is not a valid LUIS subscription key.", invalidUUID); + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + public void invalidApplicationId () { + + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + LuisApplication lA = new LuisApplication( + invalidUUID, + validUUID, + validEndpoint); + }); + + String expectedMessage = String.format("%s is not a valid LUIS application id.", invalidUUID); + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + public void invalidEndpoint() { + + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + LuisApplication lA = new LuisApplication( + validUUID, + validUUID, + invalidEndpoint); + }); + + String expectedMessage = String.format("%s is not a valid LUIS endpoint.", invalidEndpoint); + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + public void CreatesNewLuisApplication() { + + LuisApplication lA = new LuisApplication( + validUUID, + validUUID, + validEndpoint + ); + + assertTrue(lA.getApplicationId().equals(validUUID)); + assertTrue(lA.getEndpointKey().equals(validUUID)); + assertTrue(lA.getEndpoint().equals(validEndpoint)); + } + + @Test + public void CreatesNewLuisApplicationFromURL() { + String url = "https://westus.api.cognitive.microsoft.com/luis/prediction/v3.0/apps/b31aeaf3-3511-495b-a07f-571fc873214b/slots/production/predict?verbose=true&timezoneOffset=-360&subscription-key=048ec46dc58e495482b0c447cfdbd291"; + LuisApplication lA = new LuisApplication(url); + + assertTrue(lA.getApplicationId().equals("b31aeaf3-3511-495b-a07f-571fc873214b")); + assertTrue(lA.getEndpointKey().equals("048ec46dc58e495482b0c447cfdbd291")); + assertTrue(lA.getEndpoint().equals("https://westus.api.cognitive.microsoft.com")); + } + + +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisRecognizerOptionsV3Tests.java b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisRecognizerOptionsV3Tests.java new file mode 100644 index 000000000..f8015fec3 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisRecognizerOptionsV3Tests.java @@ -0,0 +1,334 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.microsoft.bot.builder.BotAdapter; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.builder.TurnContextImpl; +import com.microsoft.bot.dialogs.DialogContext; +import com.microsoft.bot.dialogs.Recognizer; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ActivityTypes; +import com.microsoft.bot.schema.ConversationReference; +import com.microsoft.bot.schema.ResourceResponse; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +public class LuisRecognizerOptionsV3Tests { + + @Mock + DialogContext dC; + + @Mock + Recognizer recognizer; + + @Mock + TurnContext turnContext; + + // Set this values to test against the service + String applicationId = "b31aeaf3-3511-495b-a07f-571fc873214b"; + String subscriptionKey = "b31aeaf3-3511-495b-a07f-571fc873214b"; + boolean mockLuisResponse = true; + + @ParameterizedTest + @ValueSource(strings = { + "Composite1.json", + "Composite2.json", + "Composite3.json", + "DateTimeReference.json", + "DynamicListsAndList.json", + "ExternalEntitiesAndBuiltin.json", + "ExternalEntitiesAndComposite.json", + "ExternalEntitiesAndList.json", + "ExternalEntitiesAndRegex.json", + "ExternalEntitiesAndSimple.json", + "ExternalEntitiesAndSimpleOverride.json", + "GeoPeopleOrdinal.json", + "Minimal.json", +// "MinimalWithGeo.json", + "NoEntitiesInstanceTrue.json", + "Patterns.json", + "Prebuilt.json", + "roles.json", + "TraceActivity.json", + "Typed.json", + "TypedPrebuilt.json" + }) // six numbers + public void shouldParseLuisResponsesCorrectly_TurnContextPassed(String fileName) { + RecognizerResult result = null, expected = null; + MockWebServer mockWebServer = new MockWebServer(); + + try { + // Get Oracle file + String content = readFileContent("/src/test/java/com/microsoft/bot/ai/luis/testdata/" + fileName); + + //Extract V3 response + ObjectMapper mapper = new ObjectMapper(); + JsonNode testData = mapper.readTree(content); + JsonNode v3SettingsAndResponse = testData.get("v3"); + JsonNode v3Response = v3SettingsAndResponse.get("response"); + + //Extract V3 Test Settings + JsonNode testSettings = v3SettingsAndResponse.get("options"); + + // Set mock response in MockWebServer + StringBuilder pathToMock = new StringBuilder("/luis/prediction/v3.0/apps/"); + String url = buildUrl(pathToMock, testSettings); + String endpoint = ""; + if (this.mockLuisResponse) { + endpoint = String.format( + "http://localhost:%s", + initializeMockServer( + mockWebServer, + v3Response, + url).port()); + } + + // Set LuisRecognizerOptions data + LuisRecognizerOptionsV3 v3 = buildTestRecognizer(endpoint, testSettings); + + // Run test + Activity activity = new Activity() { + { + setText(testData.get("text").asText()); + setType(ActivityTypes.MESSAGE); + setChannelId("EmptyContext"); + } + }; + doReturn(activity) + .when(turnContext) + .getActivity(); + + doReturn(CompletableFuture.completedFuture(new ResourceResponse())) + .when(turnContext) + .sendActivity(any(Activity.class)); + + result = v3.recognizeInternal(turnContext).get(); + + // Build expected result + expected = mapper.readValue(content, RecognizerResult.class); + Map properties = expected.getProperties(); + properties.remove("v2"); + properties.remove("v3"); + + assertEquals(mapper.writeValueAsString(expected), mapper.writeValueAsString(result)); + + RecordedRequest request = mockWebServer.takeRequest(); + assertEquals(String.format("POST %s HTTP/1.1", pathToMock.toString()), request.getRequestLine()); + assertEquals(pathToMock.toString(), request.getPath()); + + verify(turnContext, times(1)).sendActivity(any (Activity.class)); + + } catch (InterruptedException | ExecutionException | IOException e) { + e.printStackTrace(); + assertFalse(true); + } finally { + try { + mockWebServer.shutdown(); + } catch (IOException e) { + // Empty error + } + } + } + + @Test + public void shouldBuildExternalEntities_DialogContextPassed_ExternalRecognizer() { + MockWebServer mockWebServer = new MockWebServer(); + + try { + // Get Oracle file + String content = readFileContent("/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalRecognizer.json"); + + //Extract V3 response + ObjectMapper mapper = new ObjectMapper(); + JsonNode testData = mapper.readTree(content); + JsonNode v3SettingsAndResponse = testData.get("v3"); + JsonNode v3Response = v3SettingsAndResponse.get("response"); + + //Extract V3 Test Settings + JsonNode testSettings = v3SettingsAndResponse.get("options"); + + // Set mock response in MockWebServer + StringBuilder pathToMock = new StringBuilder("/luis/prediction/v3.0/apps/"); + String url = buildUrl(pathToMock, testSettings); + String endpoint = String.format( + "http://localhost:%s", + initializeMockServer( + mockWebServer, + v3Response, + url).port()); + + // Set LuisRecognizerOptions data + LuisRecognizerOptionsV3 v3 = buildTestRecognizer(endpoint, testSettings); + v3.setExternalEntityRecognizer(recognizer); + + Activity activity = new Activity() { + { + setText(testData.get("text").asText()); + setType(ActivityTypes.MESSAGE); + setChannelId("EmptyContext"); + } + }; + + doReturn(CompletableFuture.completedFuture(new ResourceResponse())) + .when(turnContext) + .sendActivity(any(Activity.class)); + + when(dC.getContext()).thenReturn(turnContext); + + doReturn(CompletableFuture.supplyAsync(() -> new RecognizerResult(){{ + setEntities(testSettings.get("ExternalRecognizerResult")); + }})) + .when(recognizer) + .recognize(any(DialogContext.class), any(Activity.class)); + + v3.recognizeInternal(dC, activity).get(); + + RecordedRequest request = mockWebServer.takeRequest(); + String resultBody = request.getBody().readUtf8(); + assertEquals("{\"query\":\"deliver 35 WA to repent harelquin\"," + + "\"options\":{\"preferExternalEntities\":true}," + + "\"externalEntities\":[{\"entityName\":\"Address\",\"startIndex\":17,\"entityLength\":16," + + "\"resolution\":[{\"endIndex\":33,\"modelType\":\"Composite Entity Extractor\"," + + "\"resolution\":{\"number\":[3],\"State\":[\"France\"]}," + + "\"startIndex\":17,\"text\":\"repent harelquin\",\"type\":\"Address\"}]}]}", + resultBody); + + } catch (InterruptedException | ExecutionException | IOException e) { + e.printStackTrace(); + assertFalse(true); + } finally { + try { + mockWebServer.shutdown(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static TurnContext createContext(String message) { + + Activity activity = new Activity() { + { + setText(message); + setType(ActivityTypes.MESSAGE); + setChannelId("EmptyContext"); + } + }; + + return new TurnContextImpl(new NotImplementedAdapter(), activity); + } + + private static class NotImplementedAdapter extends BotAdapter { + @Override + public CompletableFuture sendActivities( + TurnContext context, + List activities + ) { + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture updateActivity( + TurnContext context, + Activity activity + ) { + throw new RuntimeException(); + } + + @Override + public CompletableFuture deleteActivity( + TurnContext context, + ConversationReference reference + ) { + throw new RuntimeException(); + } + } + + private String readFileContent (String pathToFile) throws IOException { + String path = Paths.get("").toAbsolutePath().toString(); + File file = new File(path + pathToFile); + return FileUtils.readFileToString(file, "utf-8"); + } + + private String buildUrl(StringBuilder pathToMock, JsonNode testSettings) { + pathToMock.append(this.applicationId); + + if (testSettings.get("Version") != null ) { + pathToMock.append(String.format("/versions/%s/predict", testSettings.get("Version").asText())); + } else { + pathToMock.append(String.format("/slots/%s/predict", testSettings.get("Slot").asText())); + } + pathToMock.append( + String.format( + "?verbose=%s&log=%s&show-all-intents=%s", + testSettings.get("IncludeInstanceData").asText(), + testSettings.get("Log").asText(), + testSettings.get("IncludeAllIntents").asText() + ) + ); + + return pathToMock.toString(); + } + + private HttpUrl initializeMockServer(MockWebServer mockWebServer, JsonNode v3Response, String url) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + String mockResponse = mapper.writeValueAsString(v3Response); + mockWebServer.enqueue(new MockResponse() + .addHeader("Content-Type", "application/json; charset=utf-8") + .setBody(mockResponse)); + + mockWebServer.start(); + + return mockWebServer.url(url); + } + + private LuisRecognizerOptionsV3 buildTestRecognizer (String endpoint, JsonNode testSettings) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + ObjectReader readerDynamicList = mapper.readerFor(new TypeReference>() {}); + ObjectReader readerExternalentities = mapper.readerFor(new TypeReference>() {}); + return new LuisRecognizerOptionsV3( + new LuisApplication( + this.applicationId, + this.subscriptionKey, + endpoint)) {{ + setIncludeInstanceData(testSettings.get("IncludeInstanceData").asBoolean()); + setIncludeAllIntents(testSettings.get("IncludeAllIntents").asBoolean()); + setVersion(testSettings.get("Version") == null ? null : testSettings.get("Version").asText()); + setDynamicLists(testSettings.get("DynamicLists") == null ? null : readerDynamicList.readValue(testSettings.get("DynamicLists"))); + setExternalEntities(testSettings.get("ExternalEntities") == null ? null : readerExternalentities.readValue(testSettings.get("ExternalEntities"))); + setDateTimeReference(testSettings.get("DateTimeReference") == null ? null : testSettings.get("DateTimeReference").asText()); + }}; + } + +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisRecognizerTests.java b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisRecognizerTests.java new file mode 100644 index 000000000..35ae3ba07 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/LuisRecognizerTests.java @@ -0,0 +1,369 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.ai.luis; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.microsoft.bot.ai.luis.testdata.TestRecognizerResultConvert; +import com.microsoft.bot.builder.BotTelemetryClient; +import com.microsoft.bot.builder.IntentScore; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.builder.TurnContext; +import com.microsoft.bot.dialogs.DialogContext; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.ActivityTypes; +import com.microsoft.bot.schema.ChannelAccount; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class LuisRecognizerTests { + + @Mock + LuisRecognizerOptionsV3 options; + + @Mock + BotTelemetryClient telemetryClient; + + @Mock + TurnContext turnContext; + + @Mock + DialogContext dialogContext; + + @Mock + LuisApplication luisApplication; + + private RecognizerResult mockedResult = new RecognizerResult(){{ + setIntents(new HashMap(){{ + put("Test", + new IntentScore(){{ + setScore(0.2); + }}); + put("Greeting", + new IntentScore(){{ + setScore(0.4); + }}); + }}); + setEntities(JsonNodeFactory.instance.objectNode()); + setProperties( + "sentiment", + JsonNodeFactory.instance.objectNode() + .put( + "label", + "neutral")); + }}; + + @Test + public void topIntentReturnsTopIntent() { + String defaultIntent = LuisRecognizer + .topIntent(mockedResult); + assertEquals(defaultIntent, "Greeting"); + } + + @Test + public void topIntentReturnsDefaultIfMinScoreIsHigher() { + String defaultIntent = LuisRecognizer + .topIntent(mockedResult, 0.5); + assertEquals(defaultIntent, "None"); + } + + @Test + public void topIntentReturnsDefaultIfProvided() { + String defaultIntent = LuisRecognizer + .topIntent(mockedResult, "Test2", 0.5); + assertEquals(defaultIntent, "Test2"); + } + + @Test + public void topIntentThrowsIllegalArgumentIfResultIsNull() { + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + LuisRecognizer.topIntent(null); + }); + + String expectedMessage = "RecognizerResult"; + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + public void TopIntentReturnsTopIntentIfScoreEqualsMinScore() { + String defaultIntent = LuisRecognizer.topIntent(mockedResult, 0.4); + assertEquals(defaultIntent, "Greeting"); + } + + @Test + public void recognizerResult() { + setMockObjectsForTelemetry(); + LuisRecognizer recognizer = new LuisRecognizer(options); + RecognizerResult expected = new RecognizerResult(){{ + setText("Random Message"); + setIntents(new HashMap(){{ + put("Test", + new IntentScore(){{ + setScore(0.2); + }}); + put("Greeting", + new IntentScore(){{ + setScore(0.4); + }}); + }}); + setEntities(JsonNodeFactory.instance.objectNode()); + setProperties( + "sentiment", + JsonNodeFactory.instance.objectNode() + .put( + "label", + "neutral")); + }}; + RecognizerResult actual = null; + try { + actual = recognizer.recognize(turnContext).get(); + ObjectMapper mapper = new ObjectMapper(); + assertEquals(mapper.writeValueAsString(expected), mapper.writeValueAsString(actual)); + } catch (InterruptedException | ExecutionException | JsonProcessingException e) { + e.printStackTrace(); + } + } + + @Test + public void recognizerResultDialogContext() { + RecognizerResult expected = new RecognizerResult(){{ + setText("Random Message"); + setIntents(new HashMap(){{ + put("Test", + new IntentScore(){{ + setScore(0.2); + }}); + put("Greeting", + new IntentScore(){{ + setScore(0.4); + }}); + }}); + setEntities(JsonNodeFactory.instance.objectNode()); + setProperties( + "sentiment", + JsonNodeFactory.instance.objectNode() + .put( + "label", + "neutral")); + }}; + RecognizerResult actual = null; + when(turnContext.getActivity()) + .thenReturn(new Activity() {{ + setText("Random Message"); + setType(ActivityTypes.MESSAGE); + setChannelId("EmptyContext"); + setFrom(new ChannelAccount(){{ + setId("Activity-from-ID"); + }}); + }}); + + when(luisApplication.getApplicationId()) + .thenReturn("b31aeaf3-3511-495b-a07f-571fc873214b"); + + when(options.getTelemetryClient()).thenReturn(telemetryClient); + + when(options.getApplication()) + .thenReturn(luisApplication); + mockedResult.setText("Random Message"); + when(dialogContext.getContext()) + .thenReturn(turnContext); + + doReturn(CompletableFuture.supplyAsync(() -> mockedResult)) + .when(options) + .recognizeInternal( + any(DialogContext.class), any(Activity.class)); + LuisRecognizer recognizer = new LuisRecognizer(options); + try { + actual = recognizer.recognize(dialogContext, turnContext.getActivity()).get(); + ObjectMapper mapper = new ObjectMapper(); + assertEquals(mapper.writeValueAsString(expected), mapper.writeValueAsString(actual)); + } catch (InterruptedException | ExecutionException | JsonProcessingException e) { + e.printStackTrace(); + } + } + + + @Test + public void recognizerResultConverted() { + + setMockObjectsForTelemetry(); + LuisRecognizer recognizer = new LuisRecognizer(options); + TestRecognizerResultConvert actual = null; + try { + actual = recognizer.recognize(turnContext, TestRecognizerResultConvert.class).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + TestRecognizerResultConvert expected = new TestRecognizerResultConvert(){{ + recognizerResultText = "Random Message"; + }}; + + assertEquals(expected.recognizerResultText, actual.recognizerResultText); + } + + @Test + public void telemetryPropertiesAreFilledOnRecognizer() { + + setMockObjectsForTelemetry(); + LuisRecognizer recognizer = new LuisRecognizer(options); + + try { + recognizer.recognize(turnContext).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + Map expectedProperties = new HashMap (){{ + put("intentScore", "0.4"); + put("intent2", "Test"); + put("entities", "{}"); + put("intentScore2", "0.2"); + put("applicationId", "b31aeaf3-3511-495b-a07f-571fc873214b"); + put("intent", "Greeting"); + put("fromId", "Activity-from-ID"); + put("sentimentLabel", "neutral"); + }}; + + verify(telemetryClient, atLeastOnce()).trackEvent("LuisResult", expectedProperties, null); + } + + @Test + public void telemetry_PiiLogged() { + + setMockObjectsForTelemetry(); + when(options.isLogPersonalInformation()).thenReturn(true); + + LuisRecognizer recognizer = new LuisRecognizer(options); + + try { + recognizer.recognize(turnContext).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + Map expectedProperties = new HashMap (){{ + put("intentScore", "0.4"); + put("intent2", "Test"); + put("entities", "{}"); + put("intentScore2", "0.2"); + put("applicationId", "b31aeaf3-3511-495b-a07f-571fc873214b"); + put("intent", "Greeting"); + put("fromId", "Activity-from-ID"); + put("sentimentLabel", "neutral"); + put("question", "Random Message"); + }}; + + verify(telemetryClient, atLeastOnce()).trackEvent("LuisResult", expectedProperties, null); + } + + @Test + public void telemetry_additionalProperties() { + setMockObjectsForTelemetry(); + when(options.isLogPersonalInformation()).thenReturn(true); + + LuisRecognizer recognizer = new LuisRecognizer(options); + Map additionalProperties = new HashMap(){{ + put("test", "testvalue"); + put("foo", "foovalue"); + }}; + Map telemetryMetrics = new HashMap(){{ + put("test", 3.1416); + put("foo", 2.11); + }}; + try { + recognizer.recognize(turnContext, additionalProperties, telemetryMetrics).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + Map expectedProperties = new HashMap (){{ + put("intentScore", "0.4"); + put("intent2", "Test"); + put("entities", "{}"); + put("intentScore2", "0.2"); + put("applicationId", "b31aeaf3-3511-495b-a07f-571fc873214b"); + put("intent", "Greeting"); + put("fromId", "Activity-from-ID"); + put("sentimentLabel", "neutral"); + put("question", "Random Message"); + put("test", "testvalue"); + put("foo", "foovalue"); + }}; + + verify(telemetryClient, atLeastOnce()).trackEvent("LuisResult", expectedProperties, telemetryMetrics); + } + + @Test + public void telemetry_additionalPropertiesOverrideProperty() { + setMockObjectsForTelemetry(); + when(options.isLogPersonalInformation()).thenReturn(true); + + LuisRecognizer recognizer = new LuisRecognizer(options); + Map additionalProperties = new HashMap(){{ + put("intentScore", "1.15"); + put("foo", "foovalue"); + }}; + Map telemetryMetrics = new HashMap(){{ + put("test", 3.1416); + put("foo", 2.11); + }}; + try { + recognizer.recognize(turnContext, additionalProperties, telemetryMetrics).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + Map expectedProperties = new HashMap (){{ + put("intentScore", "1.15"); + put("intent2", "Test"); + put("entities", "{}"); + put("intentScore2", "0.2"); + put("applicationId", "b31aeaf3-3511-495b-a07f-571fc873214b"); + put("intent", "Greeting"); + put("fromId", "Activity-from-ID"); + put("sentimentLabel", "neutral"); + put("question", "Random Message"); + put("foo", "foovalue"); + }}; + + verify(telemetryClient, atLeastOnce()).trackEvent("LuisResult", expectedProperties, telemetryMetrics); + } + + private void setMockObjectsForTelemetry() { + when(turnContext.getActivity()) + .thenReturn(new Activity() {{ + setText("Random Message"); + setType(ActivityTypes.MESSAGE); + setChannelId("EmptyContext"); + setFrom(new ChannelAccount(){{ + setId("Activity-from-ID"); + }}); + }}); + + when(luisApplication.getApplicationId()) + .thenReturn("b31aeaf3-3511-495b-a07f-571fc873214b"); + + when(options.getTelemetryClient()).thenReturn(telemetryClient); + + when(options.getApplication()) + .thenReturn(luisApplication); + mockedResult.setText("Random Message"); + doReturn(CompletableFuture.supplyAsync(() -> mockedResult)) + .when(options) + .recognizeInternal( + any(TurnContext.class)); + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite1.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite1.json new file mode 100644 index 000000000..69ef1c20a --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite1.json @@ -0,0 +1,1971 @@ +{ + "entities": { + "$instance": { + "begin": [ + { + "endIndex": 12, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old", + "type": "builtin.age" + } + ], + "Composite1": [ + { + "endIndex": 306, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "type": "Composite1" + } + ], + "end": [ + { + "endIndex": 27, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days old", + "type": "builtin.age" + } + ], + "endpos": [ + { + "endIndex": 47, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 44, + "text": "3rd", + "type": "builtin.ordinalV2" + } + ], + "max": [ + { + "endIndex": 167, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 162, + "text": "$4.25", + "type": "builtin.currency" + } + ], + "ordinalV2": [ + { + "endIndex": 199, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 194, + "text": "first", + "type": "builtin.ordinalV2" + }, + { + "endIndex": 285, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 277, + "text": "next one", + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 306, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 294, + "text": "previous one", + "type": "builtin.ordinalV2.relative" + } + ] + }, + "begin": [ + { + "number": 12, + "units": "Year" + } + ], + "Composite1": [ + { + "$instance": { + "datetime": [ + { + "endIndex": 8, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years", + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 23, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days", + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 53, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 32, + "text": "monday july 3rd, 2019", + "type": "builtin.datetimeV2.date" + }, + { + "endIndex": 70, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 58, + "text": "every monday", + "type": "builtin.datetimeV2.set" + }, + { + "endIndex": 97, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 75, + "text": "between 3am and 5:30am", + "type": "builtin.datetimeV2.timerange" + } + ], + "dimension": [ + { + "endIndex": 109, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4 acres", + "type": "builtin.dimension" + }, + { + "endIndex": 127, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4 pico meters", + "type": "builtin.dimension" + } + ], + "email": [ + { + "endIndex": 150, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 132, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "money": [ + { + "endIndex": 157, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 155, + "text": "$4", + "type": "builtin.currency" + } + ], + "number": [ + { + "endIndex": 2, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12", + "type": "builtin.number" + }, + { + "endIndex": 18, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3", + "type": "builtin.number" + }, + { + "endIndex": 53, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "2019", + "type": "builtin.number" + }, + { + "endIndex": 92, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 91, + "text": "5", + "type": "builtin.number" + }, + { + "endIndex": 103, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4", + "type": "builtin.number" + }, + { + "endIndex": 115, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4", + "type": "builtin.number" + }, + { + "endIndex": 157, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "4", + "type": "builtin.number" + }, + { + "endIndex": 167, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 163, + "text": "4.25", + "type": "builtin.number" + }, + { + "endIndex": 179, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 177, + "text": "32", + "type": "builtin.number" + }, + { + "endIndex": 189, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 184, + "text": "210.4", + "type": "builtin.number" + }, + { + "endIndex": 206, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10", + "type": "builtin.number" + }, + { + "endIndex": 216, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5", + "type": "builtin.number" + }, + { + "endIndex": 225, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 222, + "text": "425", + "type": "builtin.number" + }, + { + "endIndex": 229, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "555", + "type": "builtin.number" + }, + { + "endIndex": 234, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 230, + "text": "1234", + "type": "builtin.number" + }, + { + "endIndex": 240, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3", + "type": "builtin.number" + }, + { + "endIndex": 258, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5", + "type": "builtin.number" + }, + { + "endIndex": 285, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 282, + "text": "one", + "type": "builtin.number" + }, + { + "endIndex": 306, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 303, + "text": "one", + "type": "builtin.number" + } + ], + "percentage": [ + { + "endIndex": 207, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10%", + "type": "builtin.percentage" + }, + { + "endIndex": 217, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5%", + "type": "builtin.percentage" + } + ], + "phonenumber": [ + { + "endIndex": 234, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 222, + "text": "425-555-1234", + "type": "builtin.phonenumber" + } + ], + "temperature": [ + { + "endIndex": 248, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3 degrees", + "type": "builtin.temperature" + }, + { + "endIndex": 268, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5 degrees c", + "type": "builtin.temperature" + } + ] + }, + "datetime": [ + { + "timex": [ + "P12Y" + ], + "type": "duration" + }, + { + "timex": [ + "P3D" + ], + "type": "duration" + }, + { + "timex": [ + "2019-07-03" + ], + "type": "date" + }, + { + "timex": [ + "XXXX-WXX-1" + ], + "type": "set" + }, + { + "timex": [ + "(T03,T05:30,PT2H30M)" + ], + "type": "timerange" + } + ], + "dimension": [ + { + "number": 4, + "units": "Acre" + }, + { + "number": 4, + "units": "Picometer" + } + ], + "email": [ + "chrimc@hotmail.com" + ], + "money": [ + { + "number": 4, + "units": "Dollar" + } + ], + "number": [ + 12, + 3, + 2019, + 5, + 4, + 4, + 4, + 4.25, + 32, + 210.4, + 10, + 10.5, + 425, + 555, + 1234, + 3, + -27.5, + 1, + 1 + ], + "percentage": [ + 10, + 10.5 + ], + "phonenumber": [ + "425-555-1234" + ], + "temperature": [ + { + "number": 3, + "units": "Degree" + }, + { + "number": -27.5, + "units": "C" + } + ] + } + ], + "end": [ + { + "number": 3, + "units": "Day" + } + ], + "endpos": [ + { + "offset": 3, + "relativeTo": "start" + } + ], + "max": [ + { + "number": 4.25, + "units": "Dollar" + } + ], + "ordinalV2": [ + { + "offset": 1, + "relativeTo": "start" + }, + { + "offset": 1, + "relativeTo": "current" + }, + { + "offset": -1, + "relativeTo": "current" + } + ] + }, + "intents": { + "Cancel": { + "score": 1.54311692E-06 + }, + "Delivery": { + "score": 0.000280677923 + }, + "EntityTests": { + "score": 0.958614767 + }, + "Greeting": { + "score": 8.076372E-07 + }, + "Help": { + "score": 4.74059061E-06 + }, + "None": { + "score": 0.0101076821 + }, + "Roles": { + "score": 0.191202149 + }, + "search": { + "score": 0.00475360872 + }, + "SpecifyName": { + "score": 7.367716E-05 + }, + "Travel": { + "score": 0.00232480234 + }, + "Weather_GetForecast": { + "score": 0.0141556319 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "compositeEntities": [ + { + "children": [ + { + "type": "builtin.datetimeV2.duration", + "value": "12 years" + }, + { + "type": "builtin.datetimeV2.duration", + "value": "3 days" + }, + { + "type": "builtin.datetimeV2.date", + "value": "monday july 3rd, 2019" + }, + { + "type": "builtin.datetimeV2.set", + "value": "every monday" + }, + { + "type": "builtin.datetimeV2.timerange", + "value": "between 3am and 5:30am" + }, + { + "type": "builtin.dimension", + "value": "4 acres" + }, + { + "type": "builtin.dimension", + "value": "4 pico meters" + }, + { + "type": "builtin.email", + "value": "chrimc@hotmail.com" + }, + { + "type": "builtin.currency", + "value": "$4" + }, + { + "type": "builtin.number", + "value": "12" + }, + { + "type": "builtin.number", + "value": "3" + }, + { + "type": "builtin.number", + "value": "2019" + }, + { + "type": "builtin.number", + "value": "5" + }, + { + "type": "builtin.number", + "value": "4" + }, + { + "type": "builtin.number", + "value": "4" + }, + { + "type": "builtin.number", + "value": "4" + }, + { + "type": "builtin.number", + "value": "4.25" + }, + { + "type": "builtin.number", + "value": "32" + }, + { + "type": "builtin.number", + "value": "210.4" + }, + { + "type": "builtin.number", + "value": "10" + }, + { + "type": "builtin.number", + "value": "10.5" + }, + { + "type": "builtin.number", + "value": "425" + }, + { + "type": "builtin.number", + "value": "555" + }, + { + "type": "builtin.number", + "value": "1234" + }, + { + "type": "builtin.number", + "value": "3" + }, + { + "type": "builtin.number", + "value": "-27.5" + }, + { + "type": "builtin.number", + "value": "one" + }, + { + "type": "builtin.number", + "value": "one" + }, + { + "type": "builtin.percentage", + "value": "10%" + }, + { + "type": "builtin.percentage", + "value": "10.5%" + }, + { + "type": "builtin.phonenumber", + "value": "425-555-1234" + }, + { + "type": "builtin.temperature", + "value": "3 degrees" + }, + { + "type": "builtin.temperature", + "value": "-27.5 degrees c" + } + ], + "parentType": "Composite1", + "value": "12 years old and 3 days old and monday july 3rd , 2019 and every monday and between 3am and 5 : 30am and 4 acres and 4 pico meters and chrimc @ hotmail . com and $ 4 and $ 4 . 25 and also 32 and 210 . 4 and first and 10 % and 10 . 5 % and 425 - 555 - 1234 and 3 degrees and - 27 . 5 degrees c and the next one and the previous one" + } + ], + "entities": [ + { + "endIndex": 305, + "entity": "12 years old and 3 days old and monday july 3rd , 2019 and every monday and between 3am and 5 : 30am and 4 acres and 4 pico meters and chrimc @ hotmail . com and $ 4 and $ 4 . 25 and also 32 and 210 . 4 and first and 10 % and 10 . 5 % and 425 - 555 - 1234 and 3 degrees and - 27 . 5 degrees c and the next one and the previous one", + "score": 0.9074669, + "startIndex": 0, + "type": "Composite1" + }, + { + "endIndex": 1, + "entity": "12", + "resolution": { + "subtype": "integer", + "value": "12" + }, + "startIndex": 0, + "type": "builtin.number" + }, + { + "endIndex": 17, + "entity": "3", + "resolution": { + "subtype": "integer", + "value": "3" + }, + "startIndex": 17, + "type": "builtin.number" + }, + { + "endIndex": 52, + "entity": "2019", + "resolution": { + "subtype": "integer", + "value": "2019" + }, + "startIndex": 49, + "type": "builtin.number" + }, + { + "endIndex": 91, + "entity": "5", + "resolution": { + "subtype": "integer", + "value": "5" + }, + "startIndex": 91, + "type": "builtin.number" + }, + { + "endIndex": 102, + "entity": "4", + "resolution": { + "subtype": "integer", + "value": "4" + }, + "startIndex": 102, + "type": "builtin.number" + }, + { + "endIndex": 114, + "entity": "4", + "resolution": { + "subtype": "integer", + "value": "4" + }, + "startIndex": 114, + "type": "builtin.number" + }, + { + "endIndex": 156, + "entity": "4", + "resolution": { + "subtype": "integer", + "value": "4" + }, + "startIndex": 156, + "type": "builtin.number" + }, + { + "endIndex": 166, + "entity": "4.25", + "resolution": { + "subtype": "decimal", + "value": "4.25" + }, + "startIndex": 163, + "type": "builtin.number" + }, + { + "endIndex": 178, + "entity": "32", + "resolution": { + "subtype": "integer", + "value": "32" + }, + "startIndex": 177, + "type": "builtin.number" + }, + { + "endIndex": 188, + "entity": "210.4", + "resolution": { + "subtype": "decimal", + "value": "210.4" + }, + "startIndex": 184, + "type": "builtin.number" + }, + { + "endIndex": 205, + "entity": "10", + "resolution": { + "subtype": "integer", + "value": "10" + }, + "startIndex": 204, + "type": "builtin.number" + }, + { + "endIndex": 215, + "entity": "10.5", + "resolution": { + "subtype": "decimal", + "value": "10.5" + }, + "startIndex": 212, + "type": "builtin.number" + }, + { + "endIndex": 224, + "entity": "425", + "resolution": { + "subtype": "integer", + "value": "425" + }, + "startIndex": 222, + "type": "builtin.number" + }, + { + "endIndex": 228, + "entity": "555", + "resolution": { + "subtype": "integer", + "value": "555" + }, + "startIndex": 226, + "type": "builtin.number" + }, + { + "endIndex": 233, + "entity": "1234", + "resolution": { + "subtype": "integer", + "value": "1234" + }, + "startIndex": 230, + "type": "builtin.number" + }, + { + "endIndex": 239, + "entity": "3", + "resolution": { + "subtype": "integer", + "value": "3" + }, + "startIndex": 239, + "type": "builtin.number" + }, + { + "endIndex": 257, + "entity": "-27.5", + "resolution": { + "subtype": "decimal", + "value": "-27.5" + }, + "startIndex": 253, + "type": "builtin.number" + }, + { + "endIndex": 284, + "entity": "one", + "resolution": { + "subtype": "integer", + "value": "1" + }, + "startIndex": 282, + "type": "builtin.number" + }, + { + "endIndex": 305, + "entity": "one", + "resolution": { + "subtype": "integer", + "value": "1" + }, + "startIndex": 303, + "type": "builtin.number" + }, + { + "endIndex": 11, + "entity": "12 years old", + "resolution": { + "unit": "Year", + "value": "12" + }, + "role": "begin", + "startIndex": 0, + "type": "builtin.age" + }, + { + "endIndex": 26, + "entity": "3 days old", + "resolution": { + "unit": "Day", + "value": "3" + }, + "role": "end", + "startIndex": 17, + "type": "builtin.age" + }, + { + "endIndex": 7, + "entity": "12 years", + "resolution": { + "values": [ + { + "timex": "P12Y", + "type": "duration", + "value": "378432000" + } + ] + }, + "startIndex": 0, + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 22, + "entity": "3 days", + "resolution": { + "values": [ + { + "timex": "P3D", + "type": "duration", + "value": "259200" + } + ] + }, + "startIndex": 17, + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 52, + "entity": "monday july 3rd, 2019", + "resolution": { + "values": [ + { + "timex": "2019-07-03", + "type": "date", + "value": "2019-07-03" + } + ] + }, + "startIndex": 32, + "type": "builtin.datetimeV2.date" + }, + { + "endIndex": 69, + "entity": "every monday", + "resolution": { + "values": [ + { + "timex": "XXXX-WXX-1", + "type": "set", + "value": "not resolved" + } + ] + }, + "startIndex": 58, + "type": "builtin.datetimeV2.set" + }, + { + "endIndex": 96, + "entity": "between 3am and 5:30am", + "resolution": { + "values": [ + { + "end": "05:30:00", + "start": "03:00:00", + "timex": "(T03,T05:30,PT2H30M)", + "type": "timerange" + } + ] + }, + "startIndex": 75, + "type": "builtin.datetimeV2.timerange" + }, + { + "endIndex": 108, + "entity": "4 acres", + "resolution": { + "unit": "Acre", + "value": "4" + }, + "startIndex": 102, + "type": "builtin.dimension" + }, + { + "endIndex": 126, + "entity": "4 pico meters", + "resolution": { + "unit": "Picometer", + "value": "4" + }, + "startIndex": 114, + "type": "builtin.dimension" + }, + { + "endIndex": 149, + "entity": "chrimc@hotmail.com", + "resolution": { + "value": "chrimc@hotmail.com" + }, + "startIndex": 132, + "type": "builtin.email" + }, + { + "endIndex": 156, + "entity": "$4", + "resolution": { + "unit": "Dollar", + "value": "4" + }, + "startIndex": 155, + "type": "builtin.currency" + }, + { + "endIndex": 166, + "entity": "$4.25", + "resolution": { + "unit": "Dollar", + "value": "4.25" + }, + "role": "max", + "startIndex": 162, + "type": "builtin.currency" + }, + { + "endIndex": 46, + "entity": "3rd", + "resolution": { + "offset": "3", + "relativeTo": "start" + }, + "role": "endpos", + "startIndex": 44, + "type": "builtin.ordinalV2" + }, + { + "endIndex": 198, + "entity": "first", + "resolution": { + "offset": "1", + "relativeTo": "start" + }, + "startIndex": 194, + "type": "builtin.ordinalV2" + }, + { + "endIndex": 284, + "entity": "next one", + "resolution": { + "offset": "1", + "relativeTo": "current" + }, + "startIndex": 277, + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 305, + "entity": "previous one", + "resolution": { + "offset": "-1", + "relativeTo": "current" + }, + "startIndex": 294, + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 206, + "entity": "10%", + "resolution": { + "value": "10%" + }, + "startIndex": 204, + "type": "builtin.percentage" + }, + { + "endIndex": 216, + "entity": "10.5%", + "resolution": { + "value": "10.5%" + }, + "startIndex": 212, + "type": "builtin.percentage" + }, + { + "endIndex": 233, + "entity": "425-555-1234", + "resolution": { + "score": "0.9", + "value": "425-555-1234" + }, + "startIndex": 222, + "type": "builtin.phonenumber" + }, + { + "endIndex": 247, + "entity": "3 degrees", + "resolution": { + "unit": "Degree", + "value": "3" + }, + "startIndex": 239, + "type": "builtin.temperature" + }, + { + "endIndex": 267, + "entity": "-27.5 degrees c", + "resolution": { + "unit": "C", + "value": "-27.5" + }, + "startIndex": 253, + "type": "builtin.temperature" + } + ], + "intents": [ + { + "intent": "EntityTests", + "score": 0.958614767 + }, + { + "intent": "Roles", + "score": 0.191202149 + }, + { + "intent": "Weather.GetForecast", + "score": 0.0141556319 + }, + { + "intent": "None", + "score": 0.0101076821 + }, + { + "intent": "search", + "score": 0.00475360872 + }, + { + "intent": "Travel", + "score": 0.00232480234 + }, + { + "intent": "Delivery", + "score": 0.000280677923 + }, + { + "intent": "SpecifyName", + "score": 7.367716E-05 + }, + { + "intent": "Help", + "score": 4.74059061E-06 + }, + { + "intent": "Cancel", + "score": 1.54311692E-06 + }, + { + "intent": "Greeting", + "score": 8.076372E-07 + } + ], + "query": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "EntityTests", + "score": 0.958614767 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "begin": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "begin", + "startIndex": 0, + "text": "12 years old", + "type": "builtin.age" + } + ], + "Composite1": [ + { + "length": 306, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "type": "Composite1" + } + ], + "end": [ + { + "length": 10, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "end", + "startIndex": 17, + "text": "3 days old", + "type": "builtin.age" + } + ], + "endpos": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "endpos", + "startIndex": 44, + "text": "3rd", + "type": "builtin.ordinalV2" + } + ], + "max": [ + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "max", + "startIndex": 162, + "text": "$4.25", + "type": "builtin.currency" + } + ], + "ordinalV2": [ + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 194, + "text": "first", + "type": "builtin.ordinalV2" + }, + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 277, + "text": "next one", + "type": "builtin.ordinalV2.relative" + }, + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 294, + "text": "previous one", + "type": "builtin.ordinalV2.relative" + } + ] + }, + "begin": [ + { + "number": 12, + "units": "Year" + } + ], + "Composite1": [ + { + "$instance": { + "datetimeV2": [ + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 6, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 21, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 32, + "text": "monday july 3rd, 2019", + "type": "builtin.datetimeV2.date" + }, + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 58, + "text": "every monday", + "type": "builtin.datetimeV2.set" + }, + { + "length": 22, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 75, + "text": "between 3am and 5:30am", + "type": "builtin.datetimeV2.timerange" + } + ], + "dimension": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4 acres", + "type": "builtin.dimension" + }, + { + "length": 13, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4 pico meters", + "type": "builtin.dimension" + } + ], + "email": [ + { + "length": 18, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 132, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "money": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 155, + "text": "$4", + "type": "builtin.currency" + } + ], + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "2019", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 91, + "text": "5", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "4", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 163, + "text": "4.25", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 177, + "text": "32", + "type": "builtin.number" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 184, + "text": "210.4", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 222, + "text": "425", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "555", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 230, + "text": "1234", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3", + "type": "builtin.number" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 282, + "text": "one", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 303, + "text": "one", + "type": "builtin.number" + } + ], + "percentage": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10%", + "type": "builtin.percentage" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5%", + "type": "builtin.percentage" + } + ], + "phonenumber": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 222, + "text": "425-555-1234", + "type": "builtin.phonenumber" + } + ], + "temperature": [ + { + "length": 9, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3 degrees", + "type": "builtin.temperature" + }, + { + "length": 15, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5 degrees c", + "type": "builtin.temperature" + } + ] + }, + "datetimeV2": [ + { + "type": "duration", + "values": [ + { + "resolution": [ + { + "value": "378432000" + } + ], + "timex": "P12Y" + } + ] + }, + { + "type": "duration", + "values": [ + { + "resolution": [ + { + "value": "259200" + } + ], + "timex": "P3D" + } + ] + }, + { + "type": "date", + "values": [ + { + "resolution": [ + { + "value": "2019-07-03" + } + ], + "timex": "2019-07-03" + } + ] + }, + { + "type": "set", + "values": [ + { + "resolution": [ + { + "value": "not resolved" + } + ], + "timex": "XXXX-WXX-1" + } + ] + }, + { + "type": "timerange", + "values": [ + { + "resolution": [ + { + "end": "05:30:00", + "start": "03:00:00" + } + ], + "timex": "(T03,T05:30,PT2H30M)" + } + ] + } + ], + "dimension": [ + { + "number": 4, + "units": "Acre" + }, + { + "number": 4, + "units": "Picometer" + } + ], + "email": [ + "chrimc@hotmail.com" + ], + "money": [ + { + "number": 4, + "units": "Dollar" + } + ], + "number": [ + 12, + 3, + 2019, + 5, + 4, + 4, + 4, + 4.25, + 32, + 210.4, + 10, + 10.5, + 425, + 555, + 1234, + 3, + -27.5, + 1, + 1 + ], + "percentage": [ + 10, + 10.5 + ], + "phonenumber": [ + "425-555-1234" + ], + "temperature": [ + { + "number": 3, + "units": "Degree" + }, + { + "number": -27.5, + "units": "C" + } + ] + } + ], + "end": [ + { + "number": 3, + "units": "Day" + } + ], + "endpos": [ + { + "offset": 3, + "relativeTo": "start" + } + ], + "max": [ + { + "number": 4.25, + "units": "Dollar" + } + ], + "ordinalV2": [ + { + "offset": 1, + "relativeTo": "start" + }, + { + "offset": 1, + "relativeTo": "current" + }, + { + "offset": -1, + "relativeTo": "current" + } + ] + }, + "intents": { + "Cancel": { + "score": 1.54311692E-06 + }, + "Delivery": { + "score": 0.000280677923 + }, + "EntityTests": { + "score": 0.958614767 + }, + "Greeting": { + "score": 8.076372E-07 + }, + "Help": { + "score": 4.74059061E-06 + }, + "None": { + "score": 0.0101076821 + }, + "Roles": { + "score": 0.191202149 + }, + "search": { + "score": 0.00475360872 + }, + "SpecifyName": { + "score": 7.367716E-05 + }, + "Travel": { + "score": 0.00232480234 + }, + "Weather.GetForecast": { + "score": 0.0141556319 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite2.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite2.json new file mode 100644 index 000000000..5d79c500f --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite2.json @@ -0,0 +1,435 @@ +{ + "entities": { + "$instance": { + "Composite2": [ + { + "endIndex": 69, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com is where you can fly from seattle to dallas via denver", + "type": "Composite2" + } + ], + "geographyV2": [ + { + "endIndex": 48, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "seattle", + "type": "builtin.geographyV2.city" + } + ], + "oldURL": [ + { + "endIndex": 14, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com", + "type": "builtin.url" + } + ] + }, + "Composite2": [ + { + "$instance": { + "City": [ + { + "endIndex": 69, + "modelType": "Hierarchical Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 63, + "text": "denver", + "type": "City" + } + ], + "From": [ + { + "endIndex": 48, + "modelType": "Hierarchical Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "seattle", + "type": "City::From" + } + ], + "To": [ + { + "endIndex": 58, + "modelType": "Hierarchical Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 52, + "text": "dallas", + "type": "City::To" + } + ] + }, + "City": [ + "denver" + ], + "From": [ + "seattle" + ], + "To": [ + "dallas" + ] + } + ], + "geographyV2": [ + { + "location": "seattle", + "type": "city" + } + ], + "oldURL": [ + "http://foo.com" + ] + }, + "intents": { + "Cancel": { + "score": 0.000219483933 + }, + "Delivery": { + "score": 0.00125586381 + }, + "EntityTests": { + "score": 0.956510365 + }, + "Greeting": { + "score": 0.00014909108 + }, + "Help": { + "score": 0.0005319686 + }, + "None": { + "score": 0.003814332 + }, + "Roles": { + "score": 0.02785043 + }, + "search": { + "score": 0.00132194813 + }, + "SpecifyName": { + "score": 0.000922683743 + }, + "Travel": { + "score": 0.01013992 + }, + "Weather_GetForecast": { + "score": 0.0228957664 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "http://foo.com is where you can fly from seattle to dallas via denver", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "compositeEntities": [ + { + "children": [ + { + "type": "City", + "value": "denver" + }, + { + "type": "City::From", + "value": "seattle" + }, + { + "type": "City::To", + "value": "dallas" + } + ], + "parentType": "Composite2", + "value": "http : / / foo . com is where you can fly from seattle to dallas via denver" + } + ], + "entities": [ + { + "endIndex": 47, + "entity": "seattle", + "score": 0.997107, + "startIndex": 41, + "type": "City::From" + }, + { + "endIndex": 57, + "entity": "dallas", + "score": 0.998217642, + "startIndex": 52, + "type": "City::To" + }, + { + "endIndex": 68, + "entity": "denver", + "score": 0.991177261, + "startIndex": 63, + "type": "City" + }, + { + "endIndex": 68, + "entity": "http : / / foo . com is where you can fly from seattle to dallas via denver", + "score": 0.9807907, + "startIndex": 0, + "type": "Composite2" + }, + { + "endIndex": 47, + "entity": "seattle", + "startIndex": 41, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 13, + "entity": "http://foo.com", + "resolution": { + "value": "http://foo.com" + }, + "role": "oldURL", + "startIndex": 0, + "type": "builtin.url" + } + ], + "intents": [ + { + "intent": "EntityTests", + "score": 0.956510365 + }, + { + "intent": "Roles", + "score": 0.02785043 + }, + { + "intent": "Weather.GetForecast", + "score": 0.0228957664 + }, + { + "intent": "Travel", + "score": 0.01013992 + }, + { + "intent": "None", + "score": 0.003814332 + }, + { + "intent": "search", + "score": 0.00132194813 + }, + { + "intent": "Delivery", + "score": 0.00125586381 + }, + { + "intent": "SpecifyName", + "score": 0.000922683743 + }, + { + "intent": "Help", + "score": 0.0005319686 + }, + { + "intent": "Cancel", + "score": 0.000219483933 + }, + { + "intent": "Greeting", + "score": 0.00014909108 + } + ], + "query": "http://foo.com is where you can fly from seattle to dallas via denver", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "EntityTests", + "score": 0.956510365 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Composite2": [ + { + "length": 69, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com is where you can fly from seattle to dallas via denver", + "type": "Composite2" + } + ], + "geographyV2": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "seattle", + "type": "builtin.geographyV2.city" + } + ], + "oldURL": [ + { + "length": 14, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "oldURL", + "startIndex": 0, + "text": "http://foo.com", + "type": "builtin.url" + } + ] + }, + "Composite2": [ + { + "$instance": { + "City": [ + { + "length": 6, + "modelType": "Hierarchical Entity Extractor", + "modelTypeId": 3, + "recognitionSources": [ + "model" + ], + "startIndex": 63, + "text": "denver", + "type": "City" + } + ], + "City::From": [ + { + "length": 7, + "modelType": "Hierarchical Entity Extractor", + "modelTypeId": 3, + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "seattle", + "type": "City::From" + } + ], + "City::To": [ + { + "length": 6, + "modelType": "Hierarchical Entity Extractor", + "modelTypeId": 3, + "recognitionSources": [ + "model" + ], + "startIndex": 52, + "text": "dallas", + "type": "City::To" + } + ] + }, + "City": [ + "denver" + ], + "City::From": [ + "seattle" + ], + "City::To": [ + "dallas" + ] + } + ], + "geographyV2": [ + { + "type": "city", + "value": "seattle" + } + ], + "oldURL": [ + "http://foo.com" + ] + }, + "intents": { + "Cancel": { + "score": 0.000219483933 + }, + "Delivery": { + "score": 0.00125586381 + }, + "EntityTests": { + "score": 0.956510365 + }, + "Greeting": { + "score": 0.00014909108 + }, + "Help": { + "score": 0.0005319686 + }, + "None": { + "score": 0.003814332 + }, + "Roles": { + "score": 0.02785043 + }, + "search": { + "score": 0.00132194813 + }, + "SpecifyName": { + "score": 0.000922683743 + }, + "Travel": { + "score": 0.01013992 + }, + "Weather.GetForecast": { + "score": 0.0228957664 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "http://foo.com is where you can fly from seattle to dallas via denver" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite3.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite3.json new file mode 100644 index 000000000..863187133 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite3.json @@ -0,0 +1,461 @@ +{ + "entities": { + "$instance": { + "Destination": [ + { + "endIndex": 33, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9818366, + "startIndex": 25, + "text": "12346 WA", + "type": "Address" + } + ], + "Source": [ + { + "endIndex": 21, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9345161, + "startIndex": 13, + "text": "12345 VA", + "type": "Address" + } + ] + }, + "Destination": [ + { + "$instance": { + "number": [ + { + "endIndex": 30, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 25, + "text": "12346", + "type": "builtin.number" + } + ], + "State": [ + { + "endIndex": 33, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9893861, + "startIndex": 31, + "text": "WA", + "type": "State" + } + ] + }, + "number": [ + 12346 + ], + "State": [ + "WA" + ] + } + ], + "Source": [ + { + "$instance": { + "number": [ + { + "endIndex": 18, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 13, + "text": "12345", + "type": "builtin.number" + } + ], + "State": [ + { + "endIndex": 21, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.941649556, + "startIndex": 19, + "text": "VA", + "type": "State" + } + ] + }, + "number": [ + 12345 + ], + "State": [ + "VA" + ] + } + ] + }, + "intents": { + "Cancel": { + "score": 1.01764708E-09 + }, + "Delivery": { + "score": 0.00238572317 + }, + "EntityTests": { + "score": 4.757576E-10 + }, + "Greeting": { + "score": 1.0875E-09 + }, + "Help": { + "score": 1.01764708E-09 + }, + "None": { + "score": 1.17844979E-06 + }, + "Roles": { + "score": 0.999911964 + }, + "search": { + "score": 9.494859E-06 + }, + "SpecifyName": { + "score": 3.0666667E-09 + }, + "Travel": { + "score": 3.09763345E-06 + }, + "Weather_GetForecast": { + "score": 1.02792524E-06 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "Deliver from 12345 VA to 12346 WA", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "compositeEntities": [ + { + "children": [ + { + "type": "builtin.number", + "value": "12345" + }, + { + "type": "State", + "value": "va" + } + ], + "parentType": "Address", + "value": "12345 va" + }, + { + "children": [ + { + "type": "builtin.number", + "value": "12346" + }, + { + "type": "State", + "value": "wa" + } + ], + "parentType": "Address", + "value": "12346 wa" + } + ], + "entities": [ + { + "endIndex": 20, + "entity": "va", + "score": 0.9684971, + "startIndex": 19, + "type": "State" + }, + { + "endIndex": 32, + "entity": "wa", + "score": 0.988121331, + "startIndex": 31, + "type": "State" + }, + { + "endIndex": 20, + "entity": "12345 va", + "role": "Source", + "score": 0.9659546, + "startIndex": 13, + "type": "Address" + }, + { + "endIndex": 32, + "entity": "12346 wa", + "role": "Destination", + "score": 0.987832844, + "startIndex": 25, + "type": "Address" + }, + { + "endIndex": 17, + "entity": "12345", + "resolution": { + "subtype": "integer", + "value": "12345" + }, + "startIndex": 13, + "type": "builtin.number" + }, + { + "endIndex": 29, + "entity": "12346", + "resolution": { + "subtype": "integer", + "value": "12346" + }, + "startIndex": 25, + "type": "builtin.number" + } + ], + "intents": [ + { + "intent": "Roles", + "score": 0.99991256 + }, + { + "intent": "Delivery", + "score": 0.00239894539 + }, + { + "intent": "None", + "score": 1.18518381E-06 + }, + { + "intent": "Weather.GetForecast", + "score": 1.03386708E-06 + }, + { + "intent": "search", + "score": 9.45E-09 + }, + { + "intent": "SpecifyName", + "score": 3.08333337E-09 + }, + { + "intent": "Travel", + "score": 3.08333337E-09 + }, + { + "intent": "Greeting", + "score": 1.09375E-09 + }, + { + "intent": "Cancel", + "score": 1.02352937E-09 + }, + { + "intent": "Help", + "score": 1.02352937E-09 + }, + { + "intent": "EntityTests", + "score": 4.617647E-10 + } + ], + "query": "Deliver from 12345 VA to 12346 WA", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "Roles", + "score": 0.99991256 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production", + "Version": "GeoPeople" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Destination": [ + { + "length": 8, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "role": "Destination", + "score": 0.9818366, + "startIndex": 25, + "text": "12346 WA", + "type": "Address" + } + ], + "Source": [ + { + "length": 8, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "role": "Source", + "score": 0.9345161, + "startIndex": 13, + "text": "12345 VA", + "type": "Address" + } + ] + }, + "Destination": [ + { + "$instance": { + "number": [ + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 25, + "text": "12346", + "type": "builtin.number" + } + ], + "State": [ + { + "length": 2, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "score": 0.9893861, + "startIndex": 31, + "text": "WA", + "type": "State" + } + ] + }, + "number": [ + 12346 + ], + "State": [ + "WA" + ] + } + ], + "Source": [ + { + "$instance": { + "number": [ + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 13, + "text": "12345", + "type": "builtin.number" + } + ], + "State": [ + { + "length": 2, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "score": 0.941649556, + "startIndex": 19, + "text": "VA", + "type": "State" + } + ] + }, + "number": [ + 12345 + ], + "State": [ + "VA" + ] + } + ] + }, + "intents": { + "Cancel": { + "score": 1.01764708E-09 + }, + "Delivery": { + "score": 0.00238572317 + }, + "EntityTests": { + "score": 4.757576E-10 + }, + "Greeting": { + "score": 1.0875E-09 + }, + "Help": { + "score": 1.01764708E-09 + }, + "None": { + "score": 1.17844979E-06 + }, + "Roles": { + "score": 0.999911964 + }, + "search": { + "score": 9.494859E-06 + }, + "SpecifyName": { + "score": 3.0666667E-09 + }, + "Travel": { + "score": 3.09763345E-06 + }, + "Weather.GetForecast": { + "score": 1.02792524E-06 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Roles" + }, + "query": "Deliver from 12345 VA to 12346 WA" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Contoso App.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Contoso App.json new file mode 100644 index 000000000..330e757bd --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Contoso App.json @@ -0,0 +1,2541 @@ +{ + "luis_schema_version": "7.0.0", + "intents": [ + { + "name": "Cancel", + "features": [] + }, + { + "name": "Delivery", + "features": [] + }, + { + "name": "EntityTests", + "features": [] + }, + { + "name": "Greeting", + "features": [] + }, + { + "name": "Help", + "features": [] + }, + { + "name": "None", + "features": [] + }, + { + "name": "Roles", + "features": [] + }, + { + "name": "search", + "features": [] + }, + { + "name": "SpecifyName", + "features": [] + }, + { + "name": "Travel", + "features": [] + }, + { + "name": "Weather.GetForecast", + "features": [] + } + ], + "entities": [ + { + "name": "Name", + "children": [], + "roles": [ + "liker", + "likee" + ], + "features": [] + }, + { + "name": "State", + "children": [], + "roles": [], + "features": [] + }, + { + "name": "Weather.Location", + "children": [], + "roles": [ + "source", + "destination" + ], + "features": [] + } + ], + "hierarchicals": [ + { + "name": "City", + "children": [ + { + "name": "To" + }, + { + "name": "From" + } + ], + "roles": [], + "features": [] + } + ], + "composites": [ + { + "name": "Address", + "children": [ + { + "name": "number" + }, + { + "name": "State" + } + ], + "roles": [ + "Source", + "Destination" + ], + "features": [] + }, + { + "name": "Composite1", + "children": [ + { + "name": "age" + }, + { + "name": "datetimeV2" + }, + { + "name": "dimension" + }, + { + "name": "email" + }, + { + "name": "money" + }, + { + "name": "number" + }, + { + "name": "percentage" + }, + { + "name": "phonenumber" + }, + { + "name": "temperature" + } + ], + "roles": [], + "features": [] + }, + { + "name": "Composite2", + "children": [ + { + "name": "Airline" + }, + { + "name": "City" + }, + { + "name": "url" + }, + { + "name": "City::From" + }, + { + "name": "City::To" + }, + { + "name": "Weather.Location" + } + ], + "roles": [], + "features": [] + } + ], + "closedLists": [ + { + "name": "Airline", + "subLists": [ + { + "canonicalForm": "Delta", + "list": [ + "DL" + ] + }, + { + "canonicalForm": "Alaska", + "list": [] + }, + { + "canonicalForm": "United", + "list": [] + }, + { + "canonicalForm": "Virgin", + "list": [ + "DL" + ] + } + ], + "roles": [ + "Buyer", + "Seller" + ] + } + ], + "prebuiltEntities": [ + { + "name": "age", + "roles": [ + "end", + "begin" + ] + }, + { + "name": "datetimeV2", + "roles": [ + "leave", + "arrive" + ] + }, + { + "name": "dimension", + "roles": [ + "length", + "width" + ] + }, + { + "name": "email", + "roles": [ + "sender", + "receiver" + ] + }, + { + "name": "geographyV2", + "roles": [ + "endloc", + "startloc" + ] + }, + { + "name": "money", + "roles": [ + "max", + "min" + ] + }, + { + "name": "number", + "roles": [] + }, + { + "name": "ordinalV2", + "roles": [ + "endpos", + "startpos" + ] + }, + { + "name": "percentage", + "roles": [ + "maximum", + "minimum" + ] + }, + { + "name": "personName", + "roles": [ + "child", + "parent" + ] + }, + { + "name": "phonenumber", + "roles": [ + "old", + "newPhone" + ] + }, + { + "name": "temperature", + "roles": [ + "a", + "b" + ] + }, + { + "name": "url", + "roles": [ + "oldURL" + ] + } + ], + "utterances": [ + { + "text": "\" i need to know the temperature at bangor , sme \"", + "intent": "Weather.GetForecast", + "entities": [] + }, + { + "text": "\" tell me perth weather , sclimate & temperature at australia \"", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 10, + "endPos": 14, + "children": [] + } + ] + }, + { + "text": "$2 and $4.25", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "$4 and $4.25", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "$4 and $99", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "$4.25 and $4", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "$99 and $4.50", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "10 years old and 4 years old", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "12 years old and 3 days old", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "12 years old and 3 days old and monday july 3rd and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "intent": "EntityTests", + "entities": [ + { + "entity": "Composite1", + "startPos": 0, + "endPos": 299, + "children": [] + } + ] + }, + { + "text": "12% and 8%", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "12% to 8%", + "intent": "Roles", + "entities": [ + { + "entity": "percentage", + "role": "minimum", + "startPos": 0, + "endPos": 2, + "children": [] + }, + { + "entity": "percentage", + "role": "maximum", + "startPos": 7, + "endPos": 8, + "children": [] + } + ] + }, + { + "text": "3 degrees and -27.5 degrees c", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "3 inches long by 2 inches wide", + "intent": "Roles", + "entities": [ + { + "entity": "dimension", + "role": "length", + "startPos": 0, + "endPos": 7, + "children": [] + }, + { + "entity": "dimension", + "role": "width", + "startPos": 17, + "endPos": 24, + "children": [] + } + ] + }, + { + "text": "3 inches long by 2 inches wide and 5% to 10% and are you between 6 years old and 8 years old and can i trade kb457 for kb922 and change 425-777-1212 to 206-666-4123 and did delta buy virgin and did the rain from hawaii get to redmond and http://foo.com changed to http://blah.com and i like between 68 degrees and 72 degrees and john likes mary and leave 3pm and arrive 5pm and pay between $400 and $500 and send chrimc@hotmail.com from emad@gmail.com", + "intent": "Roles", + "entities": [ + { + "entity": "dimension", + "role": "length", + "startPos": 0, + "endPos": 7, + "children": [] + }, + { + "entity": "dimension", + "role": "width", + "startPos": 17, + "endPos": 24, + "children": [] + }, + { + "entity": "percentage", + "role": "minimum", + "startPos": 35, + "endPos": 36, + "children": [] + }, + { + "entity": "percentage", + "role": "maximum", + "startPos": 41, + "endPos": 43, + "children": [] + }, + { + "entity": "age", + "role": "begin", + "startPos": 65, + "endPos": 75, + "children": [] + }, + { + "entity": "age", + "role": "end", + "startPos": 81, + "endPos": 91, + "children": [] + }, + { + "entity": "Part", + "role": "buy", + "startPos": 119, + "endPos": 123, + "children": [] + }, + { + "entity": "Airline", + "role": "Buyer", + "startPos": 173, + "endPos": 177, + "children": [] + }, + { + "entity": "Airline", + "role": "Seller", + "startPos": 183, + "endPos": 188, + "children": [] + }, + { + "entity": "Weather.Location", + "role": "source", + "startPos": 212, + "endPos": 217, + "children": [] + }, + { + "entity": "Weather.Location", + "role": "destination", + "startPos": 226, + "endPos": 232, + "children": [] + }, + { + "entity": "temperature", + "role": "b", + "startPos": 314, + "endPos": 323, + "children": [] + }, + { + "entity": "Name", + "role": "liker", + "startPos": 329, + "endPos": 332, + "children": [] + }, + { + "entity": "Name", + "role": "likee", + "startPos": 340, + "endPos": 343, + "children": [] + }, + { + "entity": "datetimeV2", + "role": "leave", + "startPos": 355, + "endPos": 357, + "children": [] + }, + { + "entity": "datetimeV2", + "role": "arrive", + "startPos": 370, + "endPos": 372, + "children": [] + }, + { + "entity": "money", + "role": "min", + "startPos": 390, + "endPos": 393, + "children": [] + }, + { + "entity": "money", + "role": "max", + "startPos": 399, + "endPos": 402, + "children": [] + }, + { + "entity": "email", + "role": "receiver", + "startPos": 413, + "endPos": 430, + "children": [] + } + ] + }, + { + "text": "4% and 5%", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "4% to 12%", + "intent": "Roles", + "entities": [ + { + "entity": "percentage", + "role": "minimum", + "startPos": 0, + "endPos": 1, + "children": [] + }, + { + "entity": "percentage", + "role": "maximum", + "startPos": 6, + "endPos": 8, + "children": [] + } + ] + }, + { + "text": "425-555-1212", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "425-555-1234", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "5% to 10%", + "intent": "Roles", + "entities": [ + { + "entity": "percentage", + "role": "minimum", + "startPos": 0, + "endPos": 1, + "children": [] + }, + { + "entity": "percentage", + "role": "maximum", + "startPos": 6, + "endPos": 8, + "children": [] + } + ] + }, + { + "text": "8% and 12%", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "8% and 14%", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "8% and 9%", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "8% to 12%", + "intent": "Roles", + "entities": [ + { + "entity": "percentage", + "role": "minimum", + "startPos": 0, + "endPos": 1, + "children": [] + }, + { + "entity": "percentage", + "role": "maximum", + "startPos": 6, + "endPos": 8, + "children": [] + } + ] + }, + { + "text": "9 feet long by 4 feet wide", + "intent": "Roles", + "entities": [ + { + "entity": "dimension", + "role": "length", + "startPos": 0, + "endPos": 5, + "children": [] + }, + { + "entity": "dimension", + "role": "width", + "startPos": 15, + "endPos": 20, + "children": [] + } + ] + }, + { + "text": "9.2% and 10.3%", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "abort", + "intent": "Cancel", + "entities": [] + }, + { + "text": "and $10 and $20", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "and $4 and $4.25", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "and 4$", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "and 425-765-5555", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "and can i trade kb457 for kb922", + "intent": "Roles", + "entities": [ + { + "entity": "Part", + "role": "sell", + "startPos": 16, + "endPos": 20, + "children": [] + }, + { + "entity": "Part", + "role": "buy", + "startPos": 26, + "endPos": 30, + "children": [] + } + ] + }, + { + "text": "are you between 13 years old and 16 years old", + "intent": "Roles", + "entities": [ + { + "entity": "age", + "role": "begin", + "startPos": 16, + "endPos": 27, + "children": [] + }, + { + "entity": "age", + "role": "end", + "startPos": 33, + "endPos": 44, + "children": [] + } + ] + }, + { + "text": "are you between 4 years old and 7 years old", + "intent": "Roles", + "entities": [ + { + "entity": "age", + "role": "begin", + "startPos": 16, + "endPos": 26, + "children": [] + }, + { + "entity": "age", + "role": "end", + "startPos": 32, + "endPos": 42, + "children": [] + } + ] + }, + { + "text": "are you between 6 years old and 10 years old", + "intent": "Roles", + "entities": [ + { + "entity": "age", + "role": "begin", + "startPos": 16, + "endPos": 26, + "children": [] + }, + { + "entity": "age", + "role": "end", + "startPos": 32, + "endPos": 43, + "children": [] + } + ] + }, + { + "text": "are you between 6 years old and 8 years old", + "intent": "Roles", + "entities": [ + { + "entity": "age", + "role": "end", + "startPos": 32, + "endPos": 42, + "children": [] + } + ] + }, + { + "text": "assist", + "intent": "Help", + "entities": [] + }, + { + "text": "bart simpson", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "bart simpson helps homer simpson", + "intent": "Roles", + "entities": [ + { + "entity": "personName", + "role": "child", + "startPos": 0, + "endPos": 11, + "children": [] + }, + { + "entity": "personName", + "role": "parent", + "startPos": 19, + "endPos": 31, + "children": [] + } + ] + }, + { + "text": "bart simpson is parent of lisa simpson to move calcutta to london", + "intent": "Roles", + "entities": [ + { + "entity": "personName", + "role": "parent", + "startPos": 0, + "endPos": 11, + "children": [] + }, + { + "entity": "personName", + "role": "child", + "startPos": 26, + "endPos": 37, + "children": [] + }, + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 47, + "endPos": 54, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 59, + "endPos": 64, + "children": [] + } + ] + }, + { + "text": "calcutta", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "can i trade kb457 for kb922", + "intent": "Roles", + "entities": [ + { + "entity": "Part", + "role": "sell", + "startPos": 12, + "endPos": 16, + "children": [] + }, + { + "entity": "Part", + "role": "buy", + "startPos": 22, + "endPos": 26, + "children": [] + } + ] + }, + { + "text": "can i trade kb922 for kb457", + "intent": "Roles", + "entities": [ + { + "entity": "Part", + "role": "sell", + "startPos": 12, + "endPos": 16, + "children": [] + }, + { + "entity": "Part", + "role": "buy", + "startPos": 22, + "endPos": 26, + "children": [] + } + ] + }, + { + "text": "cancel", + "intent": "Delivery", + "entities": [] + }, + { + "text": "change 425-765-1111 to 425-888-4444", + "intent": "Roles", + "entities": [ + { + "entity": "phonenumber", + "role": "old", + "startPos": 7, + "endPos": 18, + "children": [] + }, + { + "entity": "phonenumber", + "role": "newPhone", + "startPos": 23, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "change 425-777-1212 to 206-666-4123", + "intent": "Roles", + "entities": [ + { + "entity": "phonenumber", + "role": "old", + "startPos": 7, + "endPos": 18, + "children": [] + }, + { + "entity": "phonenumber", + "role": "newPhone", + "startPos": 23, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "deliver 12345 va to 12346 wa", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 8, + "endPos": 15, + "children": [] + }, + { + "entity": "State", + "startPos": 14, + "endPos": 15, + "children": [] + }, + { + "entity": "Address", + "startPos": 20, + "endPos": 27, + "children": [] + }, + { + "entity": "State", + "startPos": 26, + "endPos": 27, + "children": [] + } + ] + }, + { + "text": "delivery address is in 45654 ga", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 23, + "endPos": 30, + "children": [] + }, + { + "entity": "State", + "startPos": 29, + "endPos": 30, + "children": [] + } + ] + }, + { + "text": "did delta buy virgin", + "intent": "Roles", + "entities": [] + }, + { + "text": "did delta buy virgin?", + "intent": "Roles", + "entities": [ + { + "entity": "Airline", + "role": "Buyer", + "startPos": 4, + "endPos": 8, + "children": [] + }, + { + "entity": "Airline", + "role": "Seller", + "startPos": 14, + "endPos": 19, + "children": [] + } + ] + }, + { + "text": "did the rain from hawaii get to redmond", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "role": "source", + "startPos": 18, + "endPos": 23, + "children": [] + }, + { + "entity": "Weather.Location", + "role": "destination", + "startPos": 32, + "endPos": 38, + "children": [] + } + ] + }, + { + "text": "did virgin buy delta", + "intent": "Roles", + "entities": [ + { + "entity": "Airline", + "role": "Buyer", + "startPos": 4, + "endPos": 9, + "children": [] + }, + { + "entity": "Airline", + "role": "Seller", + "startPos": 15, + "endPos": 19, + "children": [] + } + ] + }, + { + "text": "disregard", + "intent": "Cancel", + "entities": [] + }, + { + "text": "do not do it", + "intent": "Cancel", + "entities": [] + }, + { + "text": "do not do that", + "intent": "Cancel", + "entities": [] + }, + { + "text": "don't", + "intent": "Cancel", + "entities": [] + }, + { + "text": "don't do it", + "intent": "Cancel", + "entities": [] + }, + { + "text": "don't do that", + "intent": "Cancel", + "entities": [] + }, + { + "text": "email about dogs from chris and also cats", + "intent": "search", + "entities": [] + }, + { + "text": "fly from paris, texas to chicago via stork", + "intent": "EntityTests", + "entities": [ + { + "entity": "Composite2", + "startPos": 0, + "endPos": 41, + "children": [] + } + ] + }, + { + "text": "forecast in celcius", + "intent": "Weather.GetForecast", + "entities": [] + }, + { + "text": "get florence temperature in september", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 4, + "endPos": 11, + "children": [] + } + ] + }, + { + "text": "get for me the weather conditions in sonoma county", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 37, + "endPos": 49, + "children": [] + } + ] + }, + { + "text": "get the daily temperature greenwood indiana", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 26, + "endPos": 42, + "children": [] + } + ] + }, + { + "text": "get the forcast for me", + "intent": "Weather.GetForecast", + "entities": [] + }, + { + "text": "get the weather at saint george utah", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 19, + "endPos": 35, + "children": [] + } + ] + }, + { + "text": "go from 3rd to 5th", + "intent": "Roles", + "entities": [ + { + "entity": "ordinalV2", + "role": "startpos", + "startPos": 8, + "endPos": 10, + "children": [] + }, + { + "entity": "ordinalV2", + "role": "endpos", + "startPos": 15, + "endPos": 17, + "children": [] + } + ] + }, + { + "text": "go from first to last", + "intent": "Roles", + "entities": [ + { + "entity": "ordinalV2", + "role": "startpos", + "startPos": 8, + "endPos": 12, + "children": [] + }, + { + "entity": "ordinalV2", + "role": "endpos", + "startPos": 17, + "endPos": 20, + "children": [] + } + ] + }, + { + "text": "go from next to last to last move london to jakarta and homer simpson is the parent of lisa simpson", + "intent": "Roles", + "entities": [ + { + "entity": "ordinalV2", + "role": "startpos", + "startPos": 8, + "endPos": 19, + "children": [] + }, + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 34, + "endPos": 39, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 44, + "endPos": 50, + "children": [] + }, + { + "entity": "personName", + "role": "parent", + "startPos": 56, + "endPos": 68, + "children": [] + }, + { + "entity": "personName", + "role": "child", + "startPos": 87, + "endPos": 98, + "children": [] + } + ] + }, + { + "text": "good afternoon", + "intent": "Greeting", + "entities": [] + }, + { + "text": "good evening", + "intent": "Greeting", + "entities": [] + }, + { + "text": "good morning", + "intent": "Greeting", + "entities": [] + }, + { + "text": "good night", + "intent": "Greeting", + "entities": [] + }, + { + "text": "he is yousef", + "intent": "SpecifyName", + "entities": [ + { + "entity": "Name", + "startPos": 6, + "endPos": 11, + "children": [] + } + ] + }, + { + "text": "hello", + "intent": "Cancel", + "entities": [] + }, + { + "text": "hello bot", + "intent": "Greeting", + "entities": [] + }, + { + "text": "help", + "intent": "Help", + "entities": [] + }, + { + "text": "help me", + "intent": "Help", + "entities": [] + }, + { + "text": "help me please", + "intent": "Help", + "entities": [] + }, + { + "text": "help please", + "intent": "Help", + "entities": [] + }, + { + "text": "hi", + "intent": "Greeting", + "entities": [] + }, + { + "text": "hi bot", + "intent": "Greeting", + "entities": [] + }, + { + "text": "hi emad", + "intent": "Greeting", + "entities": [] + }, + { + "text": "his name is tom", + "intent": "SpecifyName", + "entities": [ + { + "entity": "Name", + "startPos": 12, + "endPos": 14, + "children": [] + } + ] + }, + { + "text": "hiya", + "intent": "Greeting", + "entities": [] + }, + { + "text": "homer simpson is parent of bart simpson", + "intent": "Roles", + "entities": [] + }, + { + "text": "homer simpson is parent of bart simpson to move jakarta to calcutta", + "intent": "Roles", + "entities": [ + { + "entity": "personName", + "role": "child", + "startPos": 27, + "endPos": 38, + "children": [] + }, + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 48, + "endPos": 54, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 59, + "endPos": 66, + "children": [] + } + ] + }, + { + "text": "homer simpson is parent of lisa simpson", + "intent": "Roles", + "entities": [ + { + "entity": "personName", + "role": "parent", + "startPos": 0, + "endPos": 12, + "children": [] + }, + { + "entity": "personName", + "role": "child", + "startPos": 27, + "endPos": 38, + "children": [] + } + ] + }, + { + "text": "how are you", + "intent": "Greeting", + "entities": [] + }, + { + "text": "how are you doing today?", + "intent": "Greeting", + "entities": [] + }, + { + "text": "how are you doing?", + "intent": "Greeting", + "entities": [] + }, + { + "text": "how are you today?", + "intent": "Greeting", + "entities": [] + }, + { + "text": "how much rain does chambersburg get a year", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 19, + "endPos": 30, + "children": [] + } + ] + }, + { + "text": "howdy", + "intent": "Greeting", + "entities": [] + }, + { + "text": "how's it goig", + "intent": "Greeting", + "entities": [] + }, + { + "text": "http://blah.com changed to http://foo.com", + "intent": "Roles", + "entities": [ + { + "entity": "url", + "role": "oldURL", + "startPos": 0, + "endPos": 14, + "children": [] + } + ] + }, + { + "text": "http://blah.com is where you can fly from dallas to seattle via denver", + "intent": "EntityTests", + "entities": [ + { + "entity": "Composite2", + "startPos": 0, + "endPos": 69, + "children": [] + }, + { + "entity": "City::From", + "startPos": 42, + "endPos": 47, + "children": [] + }, + { + "entity": "City::To", + "startPos": 52, + "endPos": 58, + "children": [] + }, + { + "entity": "City", + "startPos": 64, + "endPos": 69, + "children": [] + } + ] + }, + { + "text": "http://foo.com", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "http://foo.com changed to http://blah.com", + "intent": "Roles", + "entities": [ + { + "entity": "url", + "role": "oldURL", + "startPos": 0, + "endPos": 13, + "children": [] + } + ] + }, + { + "text": "http://foo.com is ok", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "http://foo.com is where you can fly from seattle to dallas via denver", + "intent": "EntityTests", + "entities": [ + { + "entity": "Composite2", + "startPos": 0, + "endPos": 68, + "children": [] + }, + { + "entity": "City::From", + "startPos": 41, + "endPos": 47, + "children": [] + }, + { + "entity": "City::To", + "startPos": 52, + "endPos": 57, + "children": [] + }, + { + "entity": "City", + "startPos": 63, + "endPos": 68, + "children": [] + } + ] + }, + { + "text": "http://woof.com", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "http://woof.com is where you can fly from seattle to dallas via chicago", + "intent": "EntityTests", + "entities": [ + { + "entity": "Composite2", + "startPos": 0, + "endPos": 70, + "children": [] + }, + { + "entity": "City::From", + "startPos": 42, + "endPos": 48, + "children": [] + }, + { + "entity": "City::To", + "startPos": 53, + "endPos": 58, + "children": [] + }, + { + "entity": "City", + "startPos": 64, + "endPos": 70, + "children": [] + } + ] + }, + { + "text": "http://woof.com is where you can fly from seattle to dallas via chicago on delta", + "intent": "EntityTests", + "entities": [ + { + "entity": "Composite2", + "startPos": 0, + "endPos": 79, + "children": [] + }, + { + "entity": "City::From", + "startPos": 42, + "endPos": 48, + "children": [] + }, + { + "entity": "City::To", + "startPos": 53, + "endPos": 58, + "children": [] + }, + { + "entity": "City", + "startPos": 64, + "endPos": 70, + "children": [] + } + ] + }, + { + "text": "https://foo.com is where you can get weather for seattle", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Composite2", + "startPos": 0, + "endPos": 55, + "children": [] + }, + { + "entity": "Weather.Location", + "startPos": 49, + "endPos": 55, + "children": [] + } + ] + }, + { + "text": "i am lili", + "intent": "SpecifyName", + "entities": [ + { + "entity": "Name", + "startPos": 5, + "endPos": 8, + "children": [] + } + ] + }, + { + "text": "i am stuck", + "intent": "Help", + "entities": [] + }, + { + "text": "i like between 68 degrees and 72 degrees", + "intent": "Roles", + "entities": [ + { + "entity": "temperature", + "role": "a", + "startPos": 15, + "endPos": 24, + "children": [] + } + ] + }, + { + "text": "i like between 72 degrees and 80 degrees", + "intent": "Roles", + "entities": [ + { + "entity": "temperature", + "role": "a", + "startPos": 15, + "endPos": 24, + "children": [] + }, + { + "entity": "temperature", + "role": "b", + "startPos": 30, + "endPos": 39, + "children": [] + } + ] + }, + { + "text": "i want this in 98052 wa", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 15, + "endPos": 22, + "children": [] + }, + { + "entity": "State", + "startPos": 21, + "endPos": 22, + "children": [] + } + ] + }, + { + "text": "i want to arrive at newyork", + "intent": "Travel", + "entities": [ + { + "entity": "City::To", + "startPos": 20, + "endPos": 26, + "children": [] + } + ] + }, + { + "text": "i want to fly out of seattle", + "intent": "Travel", + "entities": [ + { + "entity": "City::From", + "startPos": 21, + "endPos": 27, + "children": [] + } + ] + }, + { + "text": "i want to know the temperature at death valley", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 34, + "endPos": 45, + "children": [] + } + ] + }, + { + "text": "i want to travel", + "intent": "Travel", + "entities": [] + }, + { + "text": "i want to travel from seattle to dallas", + "intent": "Travel", + "entities": [ + { + "entity": "City::From", + "startPos": 22, + "endPos": 28, + "children": [] + }, + { + "entity": "City::To", + "startPos": 33, + "endPos": 38, + "children": [] + } + ] + }, + { + "text": "i would like to cancel", + "intent": "Cancel", + "entities": [] + }, + { + "text": "i'll be leaving from cairo to paris", + "intent": "Travel", + "entities": [ + { + "entity": "City::From", + "startPos": 21, + "endPos": 25, + "children": [] + }, + { + "entity": "City::To", + "startPos": 30, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "i'm stuck", + "intent": "Help", + "entities": [] + }, + { + "text": "joeseph@hotmail.com", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "john likes mary", + "intent": "Roles", + "entities": [ + { + "entity": "Name", + "role": "liker", + "startPos": 0, + "endPos": 3, + "children": [] + }, + { + "entity": "Name", + "role": "likee", + "startPos": 11, + "endPos": 14, + "children": [] + } + ] + }, + { + "text": "kb409 is cool", + "intent": "EntityTests", + "entities": [] + }, + { + "text": "leave 3pm and arrive 5pm", + "intent": "Roles", + "entities": [ + { + "entity": "datetimeV2", + "role": "leave", + "startPos": 6, + "endPos": 8, + "children": [] + }, + { + "entity": "datetimeV2", + "role": "arrive", + "startPos": 21, + "endPos": 23, + "children": [] + } + ] + }, + { + "text": "mayday", + "intent": "Help", + "entities": [] + }, + { + "text": "move calcutta to mumbai", + "intent": "Roles", + "entities": [ + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 5, + "endPos": 12, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 17, + "endPos": 22, + "children": [] + } + ] + }, + { + "text": "move jakarta to london", + "intent": "Roles", + "entities": [ + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 5, + "endPos": 11, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 16, + "endPos": 21, + "children": [] + } + ] + }, + { + "text": "move london to calcutta", + "intent": "Roles", + "entities": [ + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 5, + "endPos": 10, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 15, + "endPos": 22, + "children": [] + } + ] + }, + { + "text": "move london to jakarta", + "intent": "Roles", + "entities": [ + { + "entity": "geographyV2", + "role": "startloc", + "startPos": 5, + "endPos": 10, + "children": [] + }, + { + "entity": "geographyV2", + "role": "endloc", + "startPos": 15, + "endPos": 21, + "children": [] + } + ] + }, + { + "text": "my name is emad", + "intent": "SpecifyName", + "entities": [ + { + "entity": "Name", + "startPos": 11, + "endPos": 14, + "children": [] + } + ] + }, + { + "text": "my water bottle is green.", + "intent": "None", + "entities": [] + }, + { + "text": "never mind", + "intent": "Cancel", + "entities": [] + }, + { + "text": "no thanks", + "intent": "Cancel", + "entities": [] + }, + { + "text": "nope", + "intent": "Cancel", + "entities": [] + }, + { + "text": "pay between $4 and $4.25", + "intent": "Roles", + "entities": [ + { + "entity": "money", + "role": "min", + "startPos": 12, + "endPos": 13, + "children": [] + }, + { + "entity": "money", + "role": "max", + "startPos": 19, + "endPos": 23, + "children": [] + } + ] + }, + { + "text": "pay between $4 and $40", + "intent": "Roles", + "entities": [ + { + "entity": "money", + "role": "min", + "startPos": 12, + "endPos": 13, + "children": [] + }, + { + "entity": "money", + "role": "max", + "startPos": 19, + "endPos": 21, + "children": [] + } + ] + }, + { + "text": "pay between $400 and $500", + "intent": "Roles", + "entities": [ + { + "entity": "money", + "role": "min", + "startPos": 12, + "endPos": 15, + "children": [] + }, + { + "entity": "money", + "role": "max", + "startPos": 21, + "endPos": 24, + "children": [] + } + ] + }, + { + "text": "please cancel", + "intent": "Cancel", + "entities": [] + }, + { + "text": "please deliver february 2nd 2001", + "intent": "Delivery", + "entities": [] + }, + { + "text": "please deliver to 98033 wa", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 18, + "endPos": 25, + "children": [] + }, + { + "entity": "State", + "startPos": 24, + "endPos": 25, + "children": [] + } + ] + }, + { + "text": "please delivery it to 98033 wa", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 22, + "endPos": 29, + "children": [] + }, + { + "entity": "State", + "startPos": 28, + "endPos": 29, + "children": [] + } + ] + }, + { + "text": "please disregard", + "intent": "Cancel", + "entities": [] + }, + { + "text": "please help me", + "intent": "Help", + "entities": [] + }, + { + "text": "please stop", + "intent": "Cancel", + "entities": [] + }, + { + "text": "provide me by toronto weather please", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 14, + "endPos": 20, + "children": [] + } + ] + }, + { + "text": "send bob@foo.com from chris@ark.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 15, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 22, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "send bob@hob.com from main@gmail.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 15, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 22, + "endPos": 35, + "children": [] + } + ] + }, + { + "text": "send cancel@foo.com from help@h.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 18, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 25, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "send chrimc@hotmail.com from emad@gmail.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 22, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 29, + "endPos": 42, + "children": [] + } + ] + }, + { + "text": "send chris@ark.com from bob@foo.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 17, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 24, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "send ham@ham.com from chr@live.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 15, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 22, + "endPos": 33, + "children": [] + } + ] + }, + { + "text": "send help@h.com from cancel@foo.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 14, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 21, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "send tom@foo.com from john@hotmail.com", + "intent": "Roles", + "entities": [ + { + "entity": "email", + "role": "receiver", + "startPos": 5, + "endPos": 15, + "children": [] + }, + { + "entity": "email", + "role": "sender", + "startPos": 22, + "endPos": 37, + "children": [] + } + ] + }, + { + "text": "show average rainfall for boise", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 26, + "endPos": 30, + "children": [] + } + ] + }, + { + "text": "show me the forecast at alabama", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 24, + "endPos": 30, + "children": [] + } + ] + }, + { + "text": "soliciting today ' s weather", + "intent": "Weather.GetForecast", + "entities": [] + }, + { + "text": "sos", + "intent": "Help", + "entities": [] + }, + { + "text": "start with the first one", + "intent": "Roles", + "entities": [] + }, + { + "text": "stop", + "intent": "Cancel", + "entities": [] + }, + { + "text": "temperature of delhi in celsius please", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 15, + "endPos": 19, + "children": [] + } + ] + }, + { + "text": "the address is 66666 fl", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 15, + "endPos": 22, + "children": [] + }, + { + "entity": "State", + "startPos": 21, + "endPos": 22, + "children": [] + } + ] + }, + { + "text": "there is a large deep dish pizza in your future.", + "intent": "None", + "entities": [] + }, + { + "text": "this is chris", + "intent": "SpecifyName", + "entities": [ + { + "entity": "Name", + "startPos": 8, + "endPos": 12, + "children": [] + } + ] + }, + { + "text": "this is requested in 55555 ny", + "intent": "Delivery", + "entities": [ + { + "entity": "Address", + "startPos": 21, + "endPos": 28, + "children": [] + }, + { + "entity": "State", + "startPos": 27, + "endPos": 28, + "children": [] + } + ] + }, + { + "text": "tom likes susan", + "intent": "Roles", + "entities": [ + { + "entity": "Name", + "role": "liker", + "startPos": 0, + "endPos": 2, + "children": [] + }, + { + "entity": "Name", + "role": "likee", + "startPos": 10, + "endPos": 14, + "children": [] + } + ] + }, + { + "text": "was last year about this time as wet as it is now in the south ?", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 57, + "endPos": 61, + "children": [] + } + ] + }, + { + "text": "what ' s the weather going to be like in hawaii ?", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 41, + "endPos": 46, + "children": [] + } + ] + }, + { + "text": "what ' s the weather like in minneapolis", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 29, + "endPos": 39, + "children": [] + } + ] + }, + { + "text": "what can i say", + "intent": "Help", + "entities": [] + }, + { + "text": "what can you do", + "intent": "Help", + "entities": [] + }, + { + "text": "what can you help me with", + "intent": "Help", + "entities": [] + }, + { + "text": "what do i do now?", + "intent": "Help", + "entities": [] + }, + { + "text": "what do i do?", + "intent": "Help", + "entities": [] + }, + { + "text": "what is the rain volume in sonoma county ?", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 27, + "endPos": 39, + "children": [] + } + ] + }, + { + "text": "what is the weather in redmond ?", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 23, + "endPos": 29, + "children": [] + } + ] + }, + { + "text": "what is the weather today at 10 day durham ?", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 36, + "endPos": 41, + "children": [] + } + ] + }, + { + "text": "what to wear in march in california", + "intent": "None", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 25, + "endPos": 34, + "children": [] + } + ] + }, + { + "text": "what will the weather be tomorrow in accord new york ?", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 37, + "endPos": 51, + "children": [] + } + ] + }, + { + "text": "why doesn't this work ?", + "intent": "Help", + "entities": [] + }, + { + "text": "will it be raining in ranchi", + "intent": "Weather.GetForecast", + "entities": [ + { + "entity": "Weather.Location", + "startPos": 22, + "endPos": 27, + "children": [] + } + ] + }, + { + "text": "will it rain this weekend", + "intent": "Weather.GetForecast", + "entities": [] + }, + { + "text": "will it snow today", + "intent": "Weather.GetForecast", + "entities": [] + } + ], + "versionId": "0.2", + "name": "Contoso App V3", + "desc": "Default Intents for Azure Bot Service V2", + "culture": "en-us", + "tokenizerVersion": "1.0.0", + "patternAnyEntities": [ + { + "name": "person", + "roles": [ + "from", + "to" + ], + "explicitList": [] + }, + { + "name": "subject", + "roles": [ + "extra" + ], + "explicitList": [] + } + ], + "regex_entities": [ + { + "name": "Part", + "regexPattern": "kb[0-9]+", + "roles": [ + "sell", + "buy" + ] + } + ], + "phraselists": [], + "regex_features": [], + "patterns": [ + { + "pattern": "deliver from {Address:Source} to {Address:Destination}", + "intent": "Roles" + }, + { + "pattern": "email from {person:from} to {person:to}", + "intent": "search" + }, + { + "pattern": "email about {subject} [from {person}] [and also {subject:extra}]", + "intent": "search" + } + ], + "settings": [ + { + "name": "UseAllTrainingData", + "value": "true" + } + ] +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DateTimeReference.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DateTimeReference.json new file mode 100644 index 000000000..d7c01e6bc --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DateTimeReference.json @@ -0,0 +1,75 @@ +{ + "entities": { + "Airline": [ + [ + "Delta" + ] + ], + "datetime": [ + { + "timex": [ + "2019-05-06" + ], + "type": "date" + } + ] + }, + "intents": { + "EntityTests": { + "score": 0.190871954 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "fly on delta tomorrow", + "v3": { + "options": { + "DateTimeReference": "05/05/2019 12:00:00", + "IncludeAllIntents": false, + "IncludeAPIResults": true, + "IncludeInstanceData": false, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "Airline": [ + [ + "Delta" + ] + ], + "datetimeV2": [ + { + "type": "date", + "values": [ + { + "resolution": [ + { + "value": "2019-05-06" + } + ], + "timex": "2019-05-06" + } + ] + } + ] + }, + "intents": { + "EntityTests": { + "score": 0.190871954 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "fly on delta tomorrow" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DynamicListsAndList.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DynamicListsAndList.json new file mode 100644 index 000000000..e973384fa --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DynamicListsAndList.json @@ -0,0 +1,221 @@ +{ + "entities": { + "$instance": { + "Airline": [ + { + "endIndex": 21, + "modelType": "List Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 4, + "text": "zimbabwe airlines", + "type": "Airline" + }, + { + "endIndex": 33, + "modelType": "List Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 25, + "text": "deltaair", + "type": "Airline" + } + ], + "endloc": [ + { + "endIndex": 12, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 4, + "text": "zimbabwe", + "type": "builtin.geographyV2.countryRegion" + } + ] + }, + "Airline": [ + [ + "ZimAir" + ], + [ + "DeltaAir" + ] + ], + "endloc": [ + { + "location": "zimbabwe", + "type": "countryRegion" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.006457624 + }, + "Delivery": { + "score": 0.00599454 + }, + "EntityTests": { + "score": 0.084535785 + }, + "Greeting": { + "score": 0.005392684 + }, + "Help": { + "score": 0.005619145 + }, + "None": { + "score": 0.03300121 + }, + "Roles": { + "score": 0.0213384479 + }, + "search": { + "score": 0.000823451439 + }, + "SpecifyName": { + "score": 0.0037871073 + }, + "Travel": { + "score": 0.008902215 + }, + "Weather_GetForecast": { + "score": 0.006632081 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "fly zimbabwe airlines or deltaair", + "v3": { + "options": { + "DynamicLists": [ + { + "listEntityName": "Airline", + "requestLists": [ + { + "canonicalForm": "ZimAir", + "synonyms": [ + "zimbabwe airlines" + ] + }, + { + "canonicalForm": "DeltaAir" + } + ] + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Airline": [ + { + "length": 17, + "modelType": "List Entity Extractor", + "modelTypeId": 5, + "recognitionSources": [ + "model" + ], + "startIndex": 4, + "text": "zimbabwe airlines", + "type": "Airline" + }, + { + "length": 8, + "modelType": "List Entity Extractor", + "modelTypeId": 5, + "recognitionSources": [ + "model" + ], + "startIndex": 25, + "text": "deltaair", + "type": "Airline" + } + ], + "endloc": [ + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "endloc", + "startIndex": 4, + "text": "zimbabwe", + "type": "builtin.geographyV2.countryRegion" + } + ] + }, + "Airline": [ + [ + "ZimAir" + ], + [ + "DeltaAir" + ] + ], + "endloc": [ + { + "type": "countryRegion", + "value": "zimbabwe" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.006457624 + }, + "Delivery": { + "score": 0.00599454 + }, + "EntityTests": { + "score": 0.084535785 + }, + "Greeting": { + "score": 0.005392684 + }, + "Help": { + "score": 0.005619145 + }, + "None": { + "score": 0.03300121 + }, + "Roles": { + "score": 0.0213384479 + }, + "search": { + "score": 0.000823451439 + }, + "SpecifyName": { + "score": 0.0037871073 + }, + "Travel": { + "score": 0.008902215 + }, + "Weather.GetForecast": { + "score": 0.006632081 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "fly zimbabwe airlines or deltaair" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndBuiltin.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndBuiltin.json new file mode 100644 index 000000000..6ab4b476a --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndBuiltin.json @@ -0,0 +1,167 @@ +{ + "entities": { + "$instance": { + "number": [ + { + "endIndex": 7, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 4, + "text": "hul", + "type": "builtin.number" + }, + { + "endIndex": 13, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 12, + "text": "2", + "type": "builtin.number" + } + ] + }, + "number": [ + 8, + 2 + ] + }, + "intents": { + "Cancel": { + "score": 0.006839604 + }, + "Delivery": { + "score": 0.005634159 + }, + "EntityTests": { + "score": 0.1439953 + }, + "Greeting": { + "score": 0.004496467 + }, + "Help": { + "score": 0.005810102 + }, + "None": { + "score": 0.0134399384 + }, + "Roles": { + "score": 0.0453764722 + }, + "search": { + "score": 0.00117916975 + }, + "SpecifyName": { + "score": 0.00377203338 + }, + "Travel": { + "score": 0.00252068671 + }, + "Weather_GetForecast": { + "score": 0.009093848 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "buy hul and 2 items", + "v3": { + "options": { + "ExternalEntities": [ + { + "entityLength": 3, + "entityName": "number", + "resolution": 8, + "startIndex": 4 + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "number": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 4, + "text": "hul", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 12, + "text": "2", + "type": "builtin.number" + } + ] + }, + "number": [ + 8, + 2 + ] + }, + "intents": { + "Cancel": { + "score": 0.006839604 + }, + "Delivery": { + "score": 0.005634159 + }, + "EntityTests": { + "score": 0.1439953 + }, + "Greeting": { + "score": 0.004496467 + }, + "Help": { + "score": 0.005810102 + }, + "None": { + "score": 0.0134399384 + }, + "Roles": { + "score": 0.0453764722 + }, + "search": { + "score": 0.00117916975 + }, + "SpecifyName": { + "score": 0.00377203338 + }, + "Travel": { + "score": 0.00252068671 + }, + "Weather.GetForecast": { + "score": 0.009093848 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "buy hul and 2 items" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndComposite.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndComposite.json new file mode 100644 index 000000000..0b8a7b5c8 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndComposite.json @@ -0,0 +1,196 @@ +{ + "entities": { + "$instance": { + "Address": [ + { + "endIndex": 33, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 17, + "text": "repent harelquin", + "type": "Address" + } + ], + "number": [ + { + "endIndex": 10, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "35", + "type": "builtin.number" + } + ] + }, + "Address": [ + { + "number": [ + 3 + ], + "State": [ + "France" + ] + } + ], + "number": [ + 35 + ] + }, + "intents": { + "Cancel": { + "score": 0.00324298278 + }, + "Delivery": { + "score": 0.480763137 + }, + "EntityTests": { + "score": 0.004284346 + }, + "Greeting": { + "score": 0.00282274443 + }, + "Help": { + "score": 0.00290596974 + }, + "None": { + "score": 0.0205373727 + }, + "Roles": { + "score": 0.06780239 + }, + "search": { + "score": 0.000895992853 + }, + "SpecifyName": { + "score": 0.002745299 + }, + "Travel": { + "score": 0.00337635027 + }, + "Weather_GetForecast": { + "score": 0.00949979 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "deliver 35 WA to repent harelquin", + "v3": { + "options": { + "ExternalEntities": [ + { + "entityLength": 16, + "entityName": "Address", + "resolution": { + "number": [ + 3 + ], + "State": [ + "France" + ] + }, + "startIndex": 17 + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Address": [ + { + "length": 16, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 17, + "text": "repent harelquin", + "type": "Address" + } + ], + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "35", + "type": "builtin.number" + } + ] + }, + "Address": [ + { + "number": [ + 3 + ], + "State": [ + "France" + ] + } + ], + "number": [ + 35 + ] + }, + "intents": { + "Cancel": { + "score": 0.00324298278 + }, + "Delivery": { + "score": 0.480763137 + }, + "EntityTests": { + "score": 0.004284346 + }, + "Greeting": { + "score": 0.00282274443 + }, + "Help": { + "score": 0.00290596974 + }, + "None": { + "score": 0.0205373727 + }, + "Roles": { + "score": 0.06780239 + }, + "search": { + "score": 0.000895992853 + }, + "SpecifyName": { + "score": 0.002745299 + }, + "Travel": { + "score": 0.00337635027 + }, + "Weather.GetForecast": { + "score": 0.00949979 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Delivery" + }, + "query": "deliver 35 WA to repent harelquin" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndList.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndList.json new file mode 100644 index 000000000..c4e88f12b --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndList.json @@ -0,0 +1,177 @@ +{ + "entities": { + "$instance": { + "Airline": [ + { + "endIndex": 23, + "modelType": "List Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 7, + "text": "humberg airlines", + "type": "Airline" + }, + { + "endIndex": 32, + "modelType": "List Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 27, + "text": "Delta", + "type": "Airline" + } + ] + }, + "Airline": [ + [ + "HumAir" + ], + [ + "Delta" + ] + ] + }, + "intents": { + "Cancel": { + "score": 0.00322572654 + }, + "Delivery": { + "score": 0.00437863264 + }, + "EntityTests": { + "score": 0.07901226 + }, + "Greeting": { + "score": 0.00273721316 + }, + "Help": { + "score": 0.00294000562 + }, + "None": { + "score": 0.0279089436 + }, + "Roles": { + "score": 0.120735578 + }, + "search": { + "score": 0.000854549464 + }, + "SpecifyName": { + "score": 0.002717544 + }, + "Travel": { + "score": 0.00884681847 + }, + "Weather_GetForecast": { + "score": 0.00485026464 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "fly on humberg airlines or Delta", + "v3": { + "options": { + "ExternalEntities": [ + { + "entityLength": 16, + "entityName": "Airline", + "resolution": [ + "HumAir" + ], + "startIndex": 7 + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Airline": [ + { + "length": 16, + "modelType": "List Entity Extractor", + "modelTypeId": 5, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 7, + "text": "humberg airlines", + "type": "Airline" + }, + { + "length": 5, + "modelType": "List Entity Extractor", + "modelTypeId": 5, + "recognitionSources": [ + "model" + ], + "startIndex": 27, + "text": "Delta", + "type": "Airline" + } + ] + }, + "Airline": [ + [ + "HumAir" + ], + [ + "Delta" + ] + ] + }, + "intents": { + "Cancel": { + "score": 0.00322572654 + }, + "Delivery": { + "score": 0.00437863264 + }, + "EntityTests": { + "score": 0.07901226 + }, + "Greeting": { + "score": 0.00273721316 + }, + "Help": { + "score": 0.00294000562 + }, + "None": { + "score": 0.0279089436 + }, + "Roles": { + "score": 0.120735578 + }, + "search": { + "score": 0.000854549464 + }, + "SpecifyName": { + "score": 0.002717544 + }, + "Travel": { + "score": 0.00884681847 + }, + "Weather.GetForecast": { + "score": 0.00485026464 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Roles" + }, + "query": "fly on humberg airlines or Delta" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndRegex.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndRegex.json new file mode 100644 index 000000000..33b9fef97 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndRegex.json @@ -0,0 +1,166 @@ +{ + "entities": { + "$instance": { + "Part": [ + { + "endIndex": 5, + "modelType": "Regex Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 0, + "text": "42ski", + "type": "Part" + }, + { + "endIndex": 26, + "modelType": "Regex Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 21, + "text": "kb423", + "type": "Part" + } + ] + }, + "Part": [ + "42ski", + "kb423" + ] + }, + "intents": { + "Cancel": { + "score": 0.0128021352 + }, + "Delivery": { + "score": 0.004558195 + }, + "EntityTests": { + "score": 0.009367461 + }, + "Greeting": { + "score": 0.0025622393 + }, + "Help": { + "score": 0.0021368505 + }, + "None": { + "score": 0.2778768 + }, + "Roles": { + "score": 0.0273504611 + }, + "search": { + "score": 0.000832980848 + }, + "SpecifyName": { + "score": 0.00770643726 + }, + "Travel": { + "score": 0.00204822514 + }, + "Weather_GetForecast": { + "score": 0.009585343 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "42ski is a part like kb423", + "v3": { + "options": { + "ExternalEntities": [ + { + "entityLength": 5, + "entityName": "Part", + "startIndex": 0 + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Part": [ + { + "length": 5, + "modelType": "Regex Entity Extractor", + "modelTypeId": 8, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 0, + "text": "42ski", + "type": "Part" + }, + { + "length": 5, + "modelType": "Regex Entity Extractor", + "modelTypeId": 8, + "recognitionSources": [ + "model" + ], + "startIndex": 21, + "text": "kb423", + "type": "Part" + } + ] + }, + "Part": [ + "42ski", + "kb423" + ] + }, + "intents": { + "Cancel": { + "score": 0.0128021352 + }, + "Delivery": { + "score": 0.004558195 + }, + "EntityTests": { + "score": 0.009367461 + }, + "Greeting": { + "score": 0.0025622393 + }, + "Help": { + "score": 0.0021368505 + }, + "None": { + "score": 0.2778768 + }, + "Roles": { + "score": 0.0273504611 + }, + "search": { + "score": 0.000832980848 + }, + "SpecifyName": { + "score": 0.00770643726 + }, + "Travel": { + "score": 0.00204822514 + }, + "Weather.GetForecast": { + "score": 0.009585343 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "None" + }, + "query": "42ski is a part like kb423" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimple.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimple.json new file mode 100644 index 000000000..7fc6b25c0 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimple.json @@ -0,0 +1,232 @@ +{ + "entities": { + "$instance": { + "number": [ + { + "endIndex": 10, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "37", + "type": "builtin.number" + }, + { + "endIndex": 19, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "82", + "type": "builtin.number" + } + ], + "State": [ + { + "endIndex": 13, + "modelType": "Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 11, + "text": "wa", + "type": "State" + }, + { + "endIndex": 22, + "modelType": "Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 20, + "text": "co", + "type": "State" + } + ] + }, + "number": [ + 37, + 82 + ], + "State": [ + "wa", + { + "state": "Colorado" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.004019331 + }, + "Delivery": { + "score": 0.509761333 + }, + "EntityTests": { + "score": 0.004867602 + }, + "Greeting": { + "score": 0.002855288 + }, + "Help": { + "score": 0.00350000733 + }, + "None": { + "score": 0.0121234478 + }, + "Roles": { + "score": 0.08292572 + }, + "search": { + "score": 0.0009203224 + }, + "SpecifyName": { + "score": 0.00308484654 + }, + "Travel": { + "score": 0.00362442387 + }, + "Weather_GetForecast": { + "score": 0.01115346 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "deliver 37 wa to 82 co", + "v3": { + "options": { + "ExternalEntities": [ + { + "entityLength": 2, + "entityName": "State", + "startIndex": 11 + }, + { + "entityLength": 2, + "entityName": "State", + "resolution": { + "state": "Colorado" + }, + "startIndex": 20 + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "37", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "82", + "type": "builtin.number" + } + ], + "State": [ + { + "length": 2, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 11, + "text": "wa", + "type": "State" + }, + { + "length": 2, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 20, + "text": "co", + "type": "State" + } + ] + }, + "number": [ + 37, + 82 + ], + "State": [ + "wa", + { + "state": "Colorado" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.004019331 + }, + "Delivery": { + "score": 0.509761333 + }, + "EntityTests": { + "score": 0.004867602 + }, + "Greeting": { + "score": 0.002855288 + }, + "Help": { + "score": 0.00350000733 + }, + "None": { + "score": 0.0121234478 + }, + "Roles": { + "score": 0.08292572 + }, + "search": { + "score": 0.0009203224 + }, + "SpecifyName": { + "score": 0.00308484654 + }, + "Travel": { + "score": 0.00362442387 + }, + "Weather.GetForecast": { + "score": 0.01115346 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Delivery" + }, + "query": "deliver 37 wa to 82 co" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimpleOverride.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimpleOverride.json new file mode 100644 index 000000000..5f2080c8d --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimpleOverride.json @@ -0,0 +1,239 @@ +{ + "entities": { + "$instance": { + "number": [ + { + "endIndex": 10, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "37", + "type": "builtin.number" + }, + { + "endIndex": 19, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "82", + "type": "builtin.number" + } + ], + "State": [ + { + "endIndex": 13, + "modelType": "Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 11, + "text": "wa", + "type": "State" + }, + { + "endIndex": 22, + "modelType": "Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 20, + "text": "co", + "type": "State" + } + ] + }, + "number": [ + 37, + 82 + ], + "State": [ + { + "state": "Washington" + }, + { + "state": "Colorado" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.004019331 + }, + "Delivery": { + "score": 0.509761333 + }, + "EntityTests": { + "score": 0.004867602 + }, + "Greeting": { + "score": 0.002855288 + }, + "Help": { + "score": 0.00350000733 + }, + "None": { + "score": 0.0121234478 + }, + "Roles": { + "score": 0.08292572 + }, + "search": { + "score": 0.0009203224 + }, + "SpecifyName": { + "score": 0.00308484654 + }, + "Travel": { + "score": 0.00362442387 + }, + "Weather_GetForecast": { + "score": 0.01115346 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "deliver 37 wa to 82 co", + "v3": { + "options": { + "ExternalEntities": [ + { + "entityLength": 2, + "entityName": "State", + "resolution": { + "state": "Washington" + }, + "startIndex": 11 + }, + { + "entityLength": 2, + "entityName": "State", + "resolution": { + "state": "Colorado" + }, + "startIndex": 20 + } + ], + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "37", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "82", + "type": "builtin.number" + } + ], + "State": [ + { + "length": 2, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 11, + "text": "wa", + "type": "State" + }, + { + "length": 2, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 20, + "text": "co", + "type": "State" + } + ] + }, + "number": [ + 37, + 82 + ], + "State": [ + { + "state": "Washington" + }, + { + "state": "Colorado" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.004019331 + }, + "Delivery": { + "score": 0.509761333 + }, + "EntityTests": { + "score": 0.004867602 + }, + "Greeting": { + "score": 0.002855288 + }, + "Help": { + "score": 0.00350000733 + }, + "None": { + "score": 0.0121234478 + }, + "Roles": { + "score": 0.08292572 + }, + "search": { + "score": 0.0009203224 + }, + "SpecifyName": { + "score": 0.00308484654 + }, + "Travel": { + "score": 0.00362442387 + }, + "Weather.GetForecast": { + "score": 0.01115346 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Delivery" + }, + "query": "deliver 37 wa to 82 co" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalRecognizer.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalRecognizer.json new file mode 100644 index 000000000..05cca17b7 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalRecognizer.json @@ -0,0 +1,201 @@ +{ + "entities": { + "$instance": { + "Address": [ + { + "endIndex": 33, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 17, + "text": "repent harelquin", + "type": "Address" + } + ], + "number": [ + { + "endIndex": 10, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "35", + "type": "builtin.number" + } + ] + }, + "Address": [ + { + "number": [ + 3 + ], + "State": [ + "France" + ] + } + ], + "number": [ + 35 + ] + }, + "intents": { + "Cancel": { + "score": 0.00324298278 + }, + "Delivery": { + "score": 0.480763137 + }, + "EntityTests": { + "score": 0.004284346 + }, + "Greeting": { + "score": 0.00282274443 + }, + "Help": { + "score": 0.00290596974 + }, + "None": { + "score": 0.0205373727 + }, + "Roles": { + "score": 0.06780239 + }, + "search": { + "score": 0.000895992853 + }, + "SpecifyName": { + "score": 0.002745299 + }, + "Travel": { + "score": 0.00337635027 + }, + "Weather_GetForecast": { + "score": 0.00949979 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "deliver 35 WA to repent harelquin", + "v3": { + "options": { + "ExternalRecognizerResult": { + "$instance":{ + "Address":[ + { + "endIndex":33, + "modelType":"Composite Entity Extractor", + "resolution": { + "number": [ + 3 + ], + "State": [ + "France" + ]}, + "startIndex":17, + "text":"repent harelquin", + "type":"Address" + } + ] + } + }, + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Address": [ + { + "length": 16, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "externalEntities" + ], + "startIndex": 17, + "text": "repent harelquin", + "type": "Address" + } + ], + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "35", + "type": "builtin.number" + } + ] + }, + "Address": [ + { + "number": [ + 3 + ], + "State": [ + "France" + ] + } + ], + "number": [ + 35 + ] + }, + "intents": { + "Cancel": { + "score": 0.00324298278 + }, + "Delivery": { + "score": 0.480763137 + }, + "EntityTests": { + "score": 0.004284346 + }, + "Greeting": { + "score": 0.00282274443 + }, + "Help": { + "score": 0.00290596974 + }, + "None": { + "score": 0.0205373727 + }, + "Roles": { + "score": 0.06780239 + }, + "search": { + "score": 0.000895992853 + }, + "SpecifyName": { + "score": 0.002745299 + }, + "Travel": { + "score": 0.00337635027 + }, + "Weather.GetForecast": { + "score": 0.00949979 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Delivery" + }, + "query": "deliver 35 WA to repent harelquin" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/GeoPeopleOrdinal.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/GeoPeopleOrdinal.json new file mode 100644 index 000000000..758c2efb5 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/GeoPeopleOrdinal.json @@ -0,0 +1,436 @@ +{ + "entities": { + "$instance": { + "child": [ + { + "endIndex": 99, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 87, + "text": "lisa simpson", + "type": "builtin.personName" + } + ], + "endloc": [ + { + "endIndex": 51, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 44, + "text": "jakarta", + "type": "builtin.geographyV2.city" + } + ], + "ordinalV2": [ + { + "endIndex": 28, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 24, + "text": "last", + "type": "builtin.ordinalV2.relative" + } + ], + "parent": [ + { + "endIndex": 69, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 56, + "text": "homer simpson", + "type": "builtin.personName" + } + ], + "startloc": [ + { + "endIndex": 40, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 34, + "text": "london", + "type": "builtin.geographyV2.city" + } + ], + "startpos": [ + { + "endIndex": 20, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 8, + "text": "next to last", + "type": "builtin.ordinalV2.relative" + } + ] + }, + "child": [ + "lisa simpson" + ], + "endloc": [ + { + "location": "jakarta", + "type": "city" + } + ], + "ordinalV2": [ + { + "offset": 0, + "relativeTo": "end" + } + ], + "parent": [ + "homer simpson" + ], + "startloc": [ + { + "location": "london", + "type": "city" + } + ], + "startpos": [ + { + "offset": -1, + "relativeTo": "end" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.000106304564 + }, + "Delivery": { + "score": 0.00121616619 + }, + "EntityTests": { + "score": 0.00107762846 + }, + "Greeting": { + "score": 5.23392373E-05 + }, + "Help": { + "score": 0.000134394242 + }, + "None": { + "score": 0.0108486973 + }, + "Roles": { + "score": 0.9991838 + }, + "search": { + "score": 0.002142746 + }, + "SpecifyName": { + "score": 0.0006965211 + }, + "Travel": { + "score": 0.0046763327 + }, + "Weather_GetForecast": { + "score": 0.0105504664 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "go from next to last to last move london to jakarta and homer simpson is the parent of lisa simpson", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "entities": [ + { + "endIndex": 39, + "entity": "london", + "role": "startloc", + "startIndex": 34, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 50, + "entity": "jakarta", + "role": "endloc", + "startIndex": 44, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 19, + "entity": "next to last", + "resolution": { + "offset": "-1", + "relativeTo": "end" + }, + "role": "startpos", + "startIndex": 8, + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 27, + "entity": "last", + "resolution": { + "offset": "0", + "relativeTo": "end" + }, + "startIndex": 24, + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 68, + "entity": "homer simpson", + "role": "parent", + "startIndex": 56, + "type": "builtin.personName" + }, + { + "endIndex": 98, + "entity": "lisa simpson", + "role": "child", + "startIndex": 87, + "type": "builtin.personName" + } + ], + "intents": [ + { + "intent": "Roles", + "score": 0.9991838 + }, + { + "intent": "None", + "score": 0.0108486973 + }, + { + "intent": "Weather.GetForecast", + "score": 0.0105504664 + }, + { + "intent": "Travel", + "score": 0.0046763327 + }, + { + "intent": "search", + "score": 0.002142746 + }, + { + "intent": "Delivery", + "score": 0.00121616619 + }, + { + "intent": "EntityTests", + "score": 0.00107762846 + }, + { + "intent": "SpecifyName", + "score": 0.0006965211 + }, + { + "intent": "Help", + "score": 0.000134394242 + }, + { + "intent": "Cancel", + "score": 0.000106304564 + }, + { + "intent": "Greeting", + "score": 5.23392373E-05 + } + ], + "query": "go from next to last to last move london to jakarta and homer simpson is the parent of lisa simpson", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "Roles", + "score": 0.9991838 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "child": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "child", + "startIndex": 87, + "text": "lisa simpson", + "type": "builtin.personName" + } + ], + "endloc": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "endloc", + "startIndex": 44, + "text": "jakarta", + "type": "builtin.geographyV2.city" + } + ], + "ordinalV2": [ + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 24, + "text": "last", + "type": "builtin.ordinalV2.relative" + } + ], + "parent": [ + { + "length": 13, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "parent", + "startIndex": 56, + "text": "homer simpson", + "type": "builtin.personName" + } + ], + "startloc": [ + { + "length": 6, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "startloc", + "startIndex": 34, + "text": "london", + "type": "builtin.geographyV2.city" + } + ], + "startpos": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "startpos", + "startIndex": 8, + "text": "next to last", + "type": "builtin.ordinalV2.relative" + } + ] + }, + "child": [ + "lisa simpson" + ], + "endloc": [ + { + "type": "city", + "value": "jakarta" + } + ], + "ordinalV2": [ + { + "offset": 0, + "relativeTo": "end" + } + ], + "parent": [ + "homer simpson" + ], + "startloc": [ + { + "type": "city", + "value": "london" + } + ], + "startpos": [ + { + "offset": -1, + "relativeTo": "end" + } + ] + }, + "intents": { + "Cancel": { + "score": 0.000106304564 + }, + "Delivery": { + "score": 0.00121616619 + }, + "EntityTests": { + "score": 0.00107762846 + }, + "Greeting": { + "score": 5.23392373E-05 + }, + "Help": { + "score": 0.000134394242 + }, + "None": { + "score": 0.0108486973 + }, + "Roles": { + "score": 0.9991838 + }, + "search": { + "score": 0.002142746 + }, + "SpecifyName": { + "score": 0.0006965211 + }, + "Travel": { + "score": 0.0046763327 + }, + "Weather.GetForecast": { + "score": 0.0105504664 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Roles" + }, + "query": "go from next to last to last move london to jakarta and homer simpson is the parent of lisa simpson" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Minimal.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Minimal.json new file mode 100644 index 000000000..62a0bb45e --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Minimal.json @@ -0,0 +1,143 @@ +{ + "entities": { + "Airline": [ + [ + "Delta" + ] + ], + "datetime": [ + { + "timex": [ + "T15" + ], + "type": "time" + } + ], + "dimension": [ + { + "number": 3, + "units": "Picometer" + } + ] + }, + "intents": { + "Roles": { + "score": 0.42429316 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "fly on delta at 3pm", + "v2": { + "options": { + "IncludeAllIntents": false, + "IncludeInstanceData": false, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "entities": [ + { + "endIndex": 18, + "entity": "3pm", + "resolution": { + "values": [ + { + "timex": "T15", + "type": "time", + "value": "15:00:00" + } + ] + }, + "startIndex": 16, + "type": "builtin.datetimeV2.time" + }, + { + "endIndex": 18, + "entity": "3pm", + "resolution": { + "unit": "Picometer", + "value": "3" + }, + "startIndex": 16, + "type": "builtin.dimension" + }, + { + "endIndex": 11, + "entity": "delta", + "resolution": { + "values": [ + "Delta" + ] + }, + "startIndex": 7, + "type": "Airline" + } + ], + "query": "fly on delta at 3pm", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "Roles", + "score": 0.42429316 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": false, + "IncludeAPIResults": true, + "IncludeInstanceData": false, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "Airline": [ + [ + "Delta" + ] + ], + "datetimeV2": [ + { + "type": "time", + "values": [ + { + "resolution": [ + { + "value": "15:00:00" + } + ], + "timex": "T15" + } + ] + } + ], + "dimension": [ + { + "number": 3, + "units": "Picometer" + } + ] + }, + "intents": { + "Roles": { + "score": 0.42429316 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Roles" + }, + "query": "fly on delta at 3pm" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/MinimalWithGeo.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/MinimalWithGeo.json new file mode 100644 index 000000000..bd02086e1 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/MinimalWithGeo.json @@ -0,0 +1,672 @@ +{ + "entities": { + "geographyV2": [ + { + "location": "dallas", + "type": "city" + }, + { + "location": "texas", + "type": "state" + } + ] + }, + "intents": { + "EntityTests": { + "score": 0.466911465 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "fly to dallas, texas", + "v2": { + "options": { + "IncludeAllIntents": false, + "IncludeInstanceData": false, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "entities": [ + { + "endIndex": 12, + "entity": "dallas", + "startIndex": 7, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 19, + "entity": "texas", + "startIndex": 15, + "type": "builtin.geographyV2.state" + } + ], + "query": "fly to dallas, texas", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "EntityTests", + "score": 0.466911465 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": false, + "IncludeInstanceData": false, + "LogPersonalInformation": false, + "Slot": "production", + "Timeout": 100000.0 + }, + "response": { + "prediction": { + "entities": { + "Composite1": [ + { + "$instance": { + "age": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old", + "type": "builtin.age" + }, + { + "length": 10, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days old", + "type": "builtin.age" + } + ], + "datetimeV2": [ + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 6, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 21, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 32, + "text": "monday july 3rd, 2019", + "type": "builtin.datetimeV2.date" + }, + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 58, + "text": "every monday", + "type": "builtin.datetimeV2.set" + }, + { + "length": 22, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 75, + "text": "between 3am and 5:30am", + "type": "builtin.datetimeV2.timerange" + } + ], + "dimension": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4 acres", + "type": "builtin.dimension" + }, + { + "length": 13, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4 pico meters", + "type": "builtin.dimension" + } + ], + "email": [ + { + "length": 18, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 132, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "money": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 155, + "text": "$4", + "type": "builtin.currency" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 162, + "text": "$4.25", + "type": "builtin.currency" + } + ], + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "2019", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 91, + "text": "5", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "4", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 163, + "text": "4.25", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 177, + "text": "32", + "type": "builtin.number" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 184, + "text": "210.4", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 222, + "text": "425", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "555", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 230, + "text": "1234", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3", + "type": "builtin.number" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 282, + "text": "one", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 303, + "text": "one", + "type": "builtin.number" + } + ], + "percentage": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10%", + "type": "builtin.percentage" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5%", + "type": "builtin.percentage" + } + ], + "phonenumber": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 222, + "text": "425-555-1234", + "type": "builtin.phonenumber" + } + ], + "temperature": [ + { + "length": 9, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3 degrees", + "type": "builtin.temperature" + }, + { + "length": 15, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5 degrees c", + "type": "builtin.temperature" + } + ] + }, + "age": [ + { + "number": 12, + "unit": "Year" + }, + { + "number": 3, + "unit": "Day" + } + ], + "datetimeV2": [ + { + "type": "duration", + "values": [ + { + "timex": "P12Y", + "value": "378432000" + } + ] + }, + { + "type": "duration", + "values": [ + { + "timex": "P3D", + "value": "259200" + } + ] + }, + { + "type": "date", + "values": [ + { + "timex": "2019-07-03", + "value": "2019-07-03" + } + ] + }, + { + "type": "set", + "values": [ + { + "timex": "XXXX-WXX-1", + "value": "not resolved" + } + ] + }, + { + "type": "timerange", + "values": [ + { + "end": "05:30:00", + "start": "03:00:00", + "timex": "(T03,T05:30,PT2H30M)" + } + ] + } + ], + "dimension": [ + { + "number": 4, + "unit": "Acre" + }, + { + "number": 4, + "unit": "Picometer" + } + ], + "email": [ + "chrimc@hotmail.com" + ], + "money": [ + { + "number": 4, + "unit": "Dollar" + }, + { + "number": 4.25, + "unit": "Dollar" + } + ], + "number": [ + 12, + 3, + 2019, + 5, + 4, + 4, + 4, + 4.25, + 32, + 210.4, + 10, + 10.5, + 425, + 555, + 1234, + 3, + -27.5, + 1, + 1 + ], + "percentage": [ + 10, + 10.5 + ], + "phonenumber": [ + "425-555-1234" + ], + "temperature": [ + { + "number": 3, + "unit": "Degree" + }, + { + "number": -27.5, + "unit": "C" + } + ] + } + ], + "ordinalV2": [ + { + "offset": 3, + "relativeTo": "start" + }, + { + "offset": 1, + "relativeTo": "start" + }, + { + "offset": 1, + "relativeTo": "current" + }, + { + "offset": -1, + "relativeTo": "current" + } + ] + }, + "intents": { + "Cancel": { + "score": 1.56337478E-06 + }, + "Delivery": { + "score": 0.0002846266 + }, + "EntityTests": { + "score": 0.953405857 + }, + "Greeting": { + "score": 8.20979437E-07 + }, + "Help": { + "score": 4.81870757E-06 + }, + "None": { + "score": 0.01040122 + }, + "Roles": { + "score": 0.197366714 + }, + "search": { + "score": 0.14049834 + }, + "SpecifyName": { + "score": 0.000137732946 + }, + "Travel": { + "score": 0.0100996653 + }, + "Weather.GetForecast": { + "score": 0.0143940123 + } + }, + "normalizedQuery": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/NoEntitiesInstanceTrue.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/NoEntitiesInstanceTrue.json new file mode 100644 index 000000000..32313e0e7 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/NoEntitiesInstanceTrue.json @@ -0,0 +1,41 @@ +{ + "entities": { + "$instance": {} + }, + "intents": { + "Greeting": { + "score": 0.959510267 + } + }, + "sentiment": { + "label": "positive", + "score": 0.9431402 + }, + "text": "Hi", + "v3": { + "options": { + "IncludeAllIntents": false, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": {}, + "intents": { + "Greeting": { + "score": 0.959510267 + } + }, + "sentiment": { + "label": "positive", + "score": 0.9431402 + }, + "topIntent": "Greeting" + }, + "query": "Hi" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Patterns.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Patterns.json new file mode 100644 index 000000000..865967c22 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Patterns.json @@ -0,0 +1,363 @@ +{ + "entities": { + "$instance": { + "extra": [ + { + "endIndex": 76, + "modelType": "Pattern.Any Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 71, + "text": "kb435", + "type": "subject" + } + ], + "parent": [ + { + "endIndex": 61, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "bart simpson", + "type": "builtin.personName" + } + ], + "Part": [ + { + "endIndex": 76, + "modelType": "Regex Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 71, + "text": "kb435", + "type": "Part" + } + ], + "person": [ + { + "endIndex": 61, + "modelType": "Pattern.Any Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "bart simpson", + "type": "person" + } + ], + "subject": [ + { + "endIndex": 43, + "modelType": "Pattern.Any Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 12, + "text": "something wicked this way comes", + "type": "subject" + } + ] + }, + "extra": [ + "kb435" + ], + "parent": [ + "bart simpson" + ], + "Part": [ + "kb435" + ], + "person": [ + "bart simpson" + ], + "subject": [ + "something wicked this way comes" + ] + }, + "intents": { + "Cancel": { + "score": 1.02352937E-09 + }, + "Delivery": { + "score": 1.81E-09 + }, + "EntityTests": { + "score": 1.15439843E-05 + }, + "Greeting": { + "score": 1.09375E-09 + }, + "Help": { + "score": 1.02352937E-09 + }, + "None": { + "score": 2.394552E-06 + }, + "Roles": { + "score": 5.6224585E-06 + }, + "search": { + "score": 0.9999948 + }, + "SpecifyName": { + "score": 3.08333337E-09 + }, + "Travel": { + "score": 3.08333337E-09 + }, + "Weather_GetForecast": { + "score": 1.03386708E-06 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "email about something wicked this way comes from bart simpson and also kb435", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "entities": [ + { + "endIndex": 60, + "entity": "bart simpson", + "role": "parent", + "startIndex": 49, + "type": "builtin.personName" + }, + { + "endIndex": 75, + "entity": "kb435", + "startIndex": 71, + "type": "Part" + }, + { + "endIndex": 42, + "entity": "something wicked this way comes", + "role": "", + "startIndex": 12, + "type": "subject" + }, + { + "endIndex": 60, + "entity": "bart simpson", + "role": "", + "startIndex": 49, + "type": "person" + }, + { + "endIndex": 75, + "entity": "kb435", + "role": "extra", + "startIndex": 71, + "type": "subject" + } + ], + "intents": [ + { + "intent": "search", + "score": 0.9999948 + }, + { + "intent": "EntityTests", + "score": 1.15439843E-05 + }, + { + "intent": "Roles", + "score": 5.6224585E-06 + }, + { + "intent": "None", + "score": 2.394552E-06 + }, + { + "intent": "Weather.GetForecast", + "score": 1.03386708E-06 + }, + { + "intent": "SpecifyName", + "score": 3.08333337E-09 + }, + { + "intent": "Travel", + "score": 3.08333337E-09 + }, + { + "intent": "Delivery", + "score": 1.81E-09 + }, + { + "intent": "Greeting", + "score": 1.09375E-09 + }, + { + "intent": "Cancel", + "score": 1.02352937E-09 + }, + { + "intent": "Help", + "score": 1.02352937E-09 + } + ], + "query": "email about something wicked this way comes from bart simpson and also kb435", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "search", + "score": 0.9999948 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "extra": [ + { + "length": 5, + "modelType": "Pattern.Any Entity Extractor", + "modelTypeId": 7, + "recognitionSources": [ + "model" + ], + "role": "extra", + "startIndex": 71, + "text": "kb435", + "type": "subject" + } + ], + "parent": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "parent", + "startIndex": 49, + "text": "bart simpson", + "type": "builtin.personName" + } + ], + "Part": [ + { + "length": 5, + "modelType": "Regex Entity Extractor", + "modelTypeId": 8, + "recognitionSources": [ + "model" + ], + "startIndex": 71, + "text": "kb435", + "type": "Part" + } + ], + "person": [ + { + "length": 12, + "modelType": "Pattern.Any Entity Extractor", + "modelTypeId": 7, + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "bart simpson", + "type": "person" + } + ], + "subject": [ + { + "length": 31, + "modelType": "Pattern.Any Entity Extractor", + "modelTypeId": 7, + "recognitionSources": [ + "model" + ], + "startIndex": 12, + "text": "something wicked this way comes", + "type": "subject" + } + ] + }, + "extra": [ + "kb435" + ], + "parent": [ + "bart simpson" + ], + "Part": [ + "kb435" + ], + "person": [ + "bart simpson" + ], + "subject": [ + "something wicked this way comes" + ] + }, + "intents": { + "Cancel": { + "score": 1.02352937E-09 + }, + "Delivery": { + "score": 1.81E-09 + }, + "EntityTests": { + "score": 1.15439843E-05 + }, + "Greeting": { + "score": 1.09375E-09 + }, + "Help": { + "score": 1.02352937E-09 + }, + "None": { + "score": 2.394552E-06 + }, + "Roles": { + "score": 5.6224585E-06 + }, + "search": { + "score": 0.9999948 + }, + "SpecifyName": { + "score": 3.08333337E-09 + }, + "Travel": { + "score": 3.08333337E-09 + }, + "Weather.GetForecast": { + "score": 1.03386708E-06 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "search" + }, + "query": "email about something wicked this way comes from bart simpson and also kb435" + } + } +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Prebuilt.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Prebuilt.json new file mode 100644 index 000000000..1ccad7581 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Prebuilt.json @@ -0,0 +1,351 @@ +{ + "entities": { + "$instance": { + "Composite2": [ + { + "endIndex": 66, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com is where you can get a weather forecast for seattle", + "type": "Composite2" + } + ], + "geographyV2": [ + { + "endIndex": 66, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "builtin.geographyV2.city" + } + ], + "oldURL": [ + { + "endIndex": 14, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com", + "type": "builtin.url" + } + ] + }, + "Composite2": [ + { + "$instance": { + "Weather_Location": [ + { + "endIndex": 66, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "Weather.Location" + } + ] + }, + "Weather_Location": [ + "seattle" + ] + } + ], + "geographyV2": [ + { + "location": "seattle", + "type": "city" + } + ], + "oldURL": [ + "http://foo.com" + ] + }, + "intents": { + "Cancel": { + "score": 0.00017013021 + }, + "Delivery": { + "score": 0.00114031672 + }, + "EntityTests": { + "score": 0.286522 + }, + "Greeting": { + "score": 0.000150978623 + }, + "Help": { + "score": 0.000547617 + }, + "None": { + "score": 0.01798658 + }, + "Roles": { + "score": 0.0459664278 + }, + "search": { + "score": 0.0009428267 + }, + "SpecifyName": { + "score": 0.0009960134 + }, + "Travel": { + "score": 0.00235179346 + }, + "Weather_GetForecast": { + "score": 0.6732952 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "http://foo.com is where you can get a weather forecast for seattle", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "compositeEntities": [ + { + "children": [ + { + "type": "Weather.Location", + "value": "seattle" + } + ], + "parentType": "Composite2", + "value": "http : / / foo . com is where you can get a weather forecast for seattle" + } + ], + "entities": [ + { + "endIndex": 65, + "entity": "seattle", + "score": 0.8245291, + "startIndex": 59, + "type": "Weather.Location" + }, + { + "endIndex": 65, + "entity": "http : / / foo . com is where you can get a weather forecast for seattle", + "score": 0.6503277, + "startIndex": 0, + "type": "Composite2" + }, + { + "endIndex": 65, + "entity": "seattle", + "startIndex": 59, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 13, + "entity": "http://foo.com", + "resolution": { + "value": "http://foo.com" + }, + "role": "oldURL", + "startIndex": 0, + "type": "builtin.url" + } + ], + "intents": [ + { + "intent": "Weather.GetForecast", + "score": 0.6732952 + }, + { + "intent": "EntityTests", + "score": 0.286522 + }, + { + "intent": "Roles", + "score": 0.0459664278 + }, + { + "intent": "None", + "score": 0.01798658 + }, + { + "intent": "Travel", + "score": 0.00235179346 + }, + { + "intent": "Delivery", + "score": 0.00114031672 + }, + { + "intent": "SpecifyName", + "score": 0.0009960134 + }, + { + "intent": "search", + "score": 0.0009428267 + }, + { + "intent": "Help", + "score": 0.000547617 + }, + { + "intent": "Cancel", + "score": 0.00017013021 + }, + { + "intent": "Greeting", + "score": 0.000150978623 + } + ], + "query": "http://foo.com is where you can get a weather forecast for seattle", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "Weather.GetForecast", + "score": 0.6732952 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Composite2": [ + { + "length": 66, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com is where you can get a weather forecast for seattle", + "type": "Composite2" + } + ], + "geographyV2": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "builtin.geographyV2.city" + } + ], + "oldURL": [ + { + "length": 14, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "oldURL", + "startIndex": 0, + "text": "http://foo.com", + "type": "builtin.url" + } + ] + }, + "Composite2": [ + { + "$instance": { + "Weather.Location": [ + { + "length": 7, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "Weather.Location" + } + ] + }, + "Weather.Location": [ + "seattle" + ] + } + ], + "geographyV2": [ + { + "type": "city", + "value": "seattle" + } + ], + "oldURL": [ + "http://foo.com" + ] + }, + "intents": { + "Cancel": { + "score": 0.00017013021 + }, + "Delivery": { + "score": 0.00114031672 + }, + "EntityTests": { + "score": 0.286522 + }, + "Greeting": { + "score": 0.000150978623 + }, + "Help": { + "score": 0.000547617 + }, + "None": { + "score": 0.01798658 + }, + "Roles": { + "score": 0.0459664278 + }, + "search": { + "score": 0.0009428267 + }, + "SpecifyName": { + "score": 0.0009960134 + }, + "Travel": { + "score": 0.00235179346 + }, + "Weather.GetForecast": { + "score": 0.6732952 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Weather.GetForecast" + }, + "query": "http://foo.com is where you can get a weather forecast for seattle" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TestRecognizerResultConvert.java b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TestRecognizerResultConvert.java new file mode 100644 index 000000000..8e6f6b4bc --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TestRecognizerResultConvert.java @@ -0,0 +1,15 @@ +package com.microsoft.bot.ai.luis.testdata; + +import com.microsoft.bot.builder.RecognizerConvert; +import com.microsoft.bot.builder.RecognizerResult; + +public class TestRecognizerResultConvert implements RecognizerConvert { + + public String recognizerResultText; + + @Override + public void convert(Object result) { + RecognizerResult castedObject = ((RecognizerResult) result); + recognizerResultText = castedObject.getText(); + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TraceActivity.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TraceActivity.json new file mode 100644 index 000000000..da661fa29 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TraceActivity.json @@ -0,0 +1,247 @@ +{ + "entities": { + "$instance": { + "Name": [ + { + "endIndex": 15, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 11, + "text": "Emad", + "type": "Name" + } + ], + "personName": [ + { + "endIndex": 15, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 11, + "text": "Emad", + "type": "builtin.personName" + } + ] + }, + "Name": [ + "Emad" + ], + "personName": [ + "Emad" + ] + }, + "intents": { + "Cancel": { + "score": 0.00555860251 + }, + "Delivery": { + "score": 0.005572036 + }, + "EntityTests": { + "score": 0.006504555 + }, + "Greeting": { + "score": 0.07429792 + }, + "Help": { + "score": 0.004867298 + }, + "None": { + "score": 0.0109896818 + }, + "Roles": { + "score": 0.0382854156 + }, + "search": { + "score": 0.0006921758 + }, + "SpecifyName": { + "score": 0.794012964 + }, + "Travel": { + "score": 0.00203858572 + }, + "Weather_GetForecast": { + "score": 0.006886828 + } + }, + "sentiment": { + "label": "positive", + "score": 0.7930478 + }, + "text": "My name is Emad", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "entities": [ + { + "endIndex": 14, + "entity": "emad", + "score": 0.980508447, + "startIndex": 11, + "type": "Name" + }, + { + "endIndex": 14, + "entity": "emad", + "startIndex": 11, + "type": "builtin.personName" + } + ], + "intents": [ + { + "intent": "SpecifyName", + "score": 0.794012964 + }, + { + "intent": "Greeting", + "score": 0.07429792 + }, + { + "intent": "Roles", + "score": 0.0382854156 + }, + { + "intent": "None", + "score": 0.0109896818 + }, + { + "intent": "Weather.GetForecast", + "score": 0.006886828 + }, + { + "intent": "EntityTests", + "score": 0.006504555 + }, + { + "intent": "Delivery", + "score": 0.005572036 + }, + { + "intent": "Cancel", + "score": 0.00555860251 + }, + { + "intent": "Help", + "score": 0.004867298 + }, + { + "intent": "Travel", + "score": 0.00203858572 + }, + { + "intent": "search", + "score": 0.0006921758 + } + ], + "query": "My name is Emad", + "sentimentAnalysis": { + "label": "positive", + "score": 0.7930478 + }, + "topScoringIntent": { + "intent": "SpecifyName", + "score": 0.794012964 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Name": [ + { + "length": 4, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "startIndex": 11, + "text": "Emad", + "type": "Name" + } + ], + "personName": [ + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 11, + "text": "Emad", + "type": "builtin.personName" + } + ] + }, + "Name": [ + "Emad" + ], + "personName": [ + "Emad" + ] + }, + "intents": { + "Cancel": { + "score": 0.00555860251 + }, + "Delivery": { + "score": 0.005572036 + }, + "EntityTests": { + "score": 0.006504555 + }, + "Greeting": { + "score": 0.07429792 + }, + "Help": { + "score": 0.004867298 + }, + "None": { + "score": 0.0109896818 + }, + "Roles": { + "score": 0.0382854156 + }, + "search": { + "score": 0.0006921758 + }, + "SpecifyName": { + "score": 0.794012964 + }, + "Travel": { + "score": 0.00203858572 + }, + "Weather.GetForecast": { + "score": 0.006886828 + } + }, + "sentiment": { + "label": "positive", + "score": 0.7930478 + }, + "topIntent": "SpecifyName" + }, + "query": "My name is Emad" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Typed.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Typed.json new file mode 100644 index 000000000..88b2a1002 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Typed.json @@ -0,0 +1,1971 @@ +{ + "entities": { + "$instance": { + "begin": [ + { + "endIndex": 12, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old", + "type": "builtin.age" + } + ], + "Composite1": [ + { + "endIndex": 306, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "type": "Composite1" + } + ], + "end": [ + { + "endIndex": 27, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days old", + "type": "builtin.age" + } + ], + "endpos": [ + { + "endIndex": 47, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 44, + "text": "3rd", + "type": "builtin.ordinalV2" + } + ], + "max": [ + { + "endIndex": 167, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 162, + "text": "$4.25", + "type": "builtin.currency" + } + ], + "ordinalV2": [ + { + "endIndex": 199, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 194, + "text": "first", + "type": "builtin.ordinalV2" + }, + { + "endIndex": 285, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 277, + "text": "next one", + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 306, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 294, + "text": "previous one", + "type": "builtin.ordinalV2.relative" + } + ] + }, + "begin": [ + { + "number": 12, + "units": "Year" + } + ], + "Composite1": [ + { + "$instance": { + "datetime": [ + { + "endIndex": 8, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years", + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 23, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days", + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 53, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 32, + "text": "monday july 3rd, 2019", + "type": "builtin.datetimeV2.date" + }, + { + "endIndex": 70, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 58, + "text": "every monday", + "type": "builtin.datetimeV2.set" + }, + { + "endIndex": 97, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 75, + "text": "between 3am and 5:30am", + "type": "builtin.datetimeV2.timerange" + } + ], + "dimension": [ + { + "endIndex": 109, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4 acres", + "type": "builtin.dimension" + }, + { + "endIndex": 127, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4 pico meters", + "type": "builtin.dimension" + } + ], + "email": [ + { + "endIndex": 150, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 132, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "money": [ + { + "endIndex": 157, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 155, + "text": "$4", + "type": "builtin.currency" + } + ], + "number": [ + { + "endIndex": 2, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12", + "type": "builtin.number" + }, + { + "endIndex": 18, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3", + "type": "builtin.number" + }, + { + "endIndex": 53, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "2019", + "type": "builtin.number" + }, + { + "endIndex": 92, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 91, + "text": "5", + "type": "builtin.number" + }, + { + "endIndex": 103, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4", + "type": "builtin.number" + }, + { + "endIndex": 115, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4", + "type": "builtin.number" + }, + { + "endIndex": 157, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "4", + "type": "builtin.number" + }, + { + "endIndex": 167, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 163, + "text": "4.25", + "type": "builtin.number" + }, + { + "endIndex": 179, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 177, + "text": "32", + "type": "builtin.number" + }, + { + "endIndex": 189, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 184, + "text": "210.4", + "type": "builtin.number" + }, + { + "endIndex": 206, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10", + "type": "builtin.number" + }, + { + "endIndex": 216, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5", + "type": "builtin.number" + }, + { + "endIndex": 225, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 222, + "text": "425", + "type": "builtin.number" + }, + { + "endIndex": 229, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "555", + "type": "builtin.number" + }, + { + "endIndex": 234, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 230, + "text": "1234", + "type": "builtin.number" + }, + { + "endIndex": 240, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3", + "type": "builtin.number" + }, + { + "endIndex": 258, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5", + "type": "builtin.number" + }, + { + "endIndex": 285, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 282, + "text": "one", + "type": "builtin.number" + }, + { + "endIndex": 306, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 303, + "text": "one", + "type": "builtin.number" + } + ], + "percentage": [ + { + "endIndex": 207, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10%", + "type": "builtin.percentage" + }, + { + "endIndex": 217, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5%", + "type": "builtin.percentage" + } + ], + "phonenumber": [ + { + "endIndex": 234, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 222, + "text": "425-555-1234", + "type": "builtin.phonenumber" + } + ], + "temperature": [ + { + "endIndex": 248, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3 degrees", + "type": "builtin.temperature" + }, + { + "endIndex": 268, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5 degrees c", + "type": "builtin.temperature" + } + ] + }, + "datetime": [ + { + "timex": [ + "P12Y" + ], + "type": "duration" + }, + { + "timex": [ + "P3D" + ], + "type": "duration" + }, + { + "timex": [ + "2019-07-03" + ], + "type": "date" + }, + { + "timex": [ + "XXXX-WXX-1" + ], + "type": "set" + }, + { + "timex": [ + "(T03,T05:30,PT2H30M)" + ], + "type": "timerange" + } + ], + "dimension": [ + { + "number": 4, + "units": "Acre" + }, + { + "number": 4, + "units": "Picometer" + } + ], + "email": [ + "chrimc@hotmail.com" + ], + "money": [ + { + "number": 4, + "units": "Dollar" + } + ], + "number": [ + 12, + 3, + 2019, + 5, + 4, + 4, + 4, + 4.25, + 32, + 210.4, + 10, + 10.5, + 425, + 555, + 1234, + 3, + -27.5, + 1, + 1 + ], + "percentage": [ + 10, + 10.5 + ], + "phonenumber": [ + "425-555-1234" + ], + "temperature": [ + { + "number": 3, + "units": "Degree" + }, + { + "number": -27.5, + "units": "C" + } + ] + } + ], + "end": [ + { + "number": 3, + "units": "Day" + } + ], + "endpos": [ + { + "offset": 3, + "relativeTo": "start" + } + ], + "max": [ + { + "number": 4.25, + "units": "Dollar" + } + ], + "ordinalV2": [ + { + "offset": 1, + "relativeTo": "start" + }, + { + "offset": 1, + "relativeTo": "current" + }, + { + "offset": -1, + "relativeTo": "current" + } + ] + }, + "intents": { + "Cancel": { + "score": 1.54311692E-06 + }, + "Delivery": { + "score": 0.000280677923 + }, + "EntityTests": { + "score": 0.958614767 + }, + "Greeting": { + "score": 8.076372E-07 + }, + "Help": { + "score": 4.74059061E-06 + }, + "None": { + "score": 0.0101076821 + }, + "Roles": { + "score": 0.191202149 + }, + "search": { + "score": 0.00475360872 + }, + "SpecifyName": { + "score": 7.367716E-05 + }, + "Travel": { + "score": 0.00232480234 + }, + "Weather_GetForecast": { + "score": 0.0141556319 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "compositeEntities": [ + { + "children": [ + { + "type": "builtin.datetimeV2.duration", + "value": "12 years" + }, + { + "type": "builtin.datetimeV2.duration", + "value": "3 days" + }, + { + "type": "builtin.datetimeV2.date", + "value": "monday july 3rd, 2019" + }, + { + "type": "builtin.datetimeV2.set", + "value": "every monday" + }, + { + "type": "builtin.datetimeV2.timerange", + "value": "between 3am and 5:30am" + }, + { + "type": "builtin.dimension", + "value": "4 acres" + }, + { + "type": "builtin.dimension", + "value": "4 pico meters" + }, + { + "type": "builtin.email", + "value": "chrimc@hotmail.com" + }, + { + "type": "builtin.currency", + "value": "$4" + }, + { + "type": "builtin.number", + "value": "12" + }, + { + "type": "builtin.number", + "value": "3" + }, + { + "type": "builtin.number", + "value": "2019" + }, + { + "type": "builtin.number", + "value": "5" + }, + { + "type": "builtin.number", + "value": "4" + }, + { + "type": "builtin.number", + "value": "4" + }, + { + "type": "builtin.number", + "value": "4" + }, + { + "type": "builtin.number", + "value": "4.25" + }, + { + "type": "builtin.number", + "value": "32" + }, + { + "type": "builtin.number", + "value": "210.4" + }, + { + "type": "builtin.number", + "value": "10" + }, + { + "type": "builtin.number", + "value": "10.5" + }, + { + "type": "builtin.number", + "value": "425" + }, + { + "type": "builtin.number", + "value": "555" + }, + { + "type": "builtin.number", + "value": "1234" + }, + { + "type": "builtin.number", + "value": "3" + }, + { + "type": "builtin.number", + "value": "-27.5" + }, + { + "type": "builtin.number", + "value": "one" + }, + { + "type": "builtin.number", + "value": "one" + }, + { + "type": "builtin.percentage", + "value": "10%" + }, + { + "type": "builtin.percentage", + "value": "10.5%" + }, + { + "type": "builtin.phonenumber", + "value": "425-555-1234" + }, + { + "type": "builtin.temperature", + "value": "3 degrees" + }, + { + "type": "builtin.temperature", + "value": "-27.5 degrees c" + } + ], + "parentType": "Composite1", + "value": "12 years old and 3 days old and monday july 3rd , 2019 and every monday and between 3am and 5 : 30am and 4 acres and 4 pico meters and chrimc @ hotmail . com and $ 4 and $ 4 . 25 and also 32 and 210 . 4 and first and 10 % and 10 . 5 % and 425 - 555 - 1234 and 3 degrees and - 27 . 5 degrees c and the next one and the previous one" + } + ], + "entities": [ + { + "endIndex": 305, + "entity": "12 years old and 3 days old and monday july 3rd , 2019 and every monday and between 3am and 5 : 30am and 4 acres and 4 pico meters and chrimc @ hotmail . com and $ 4 and $ 4 . 25 and also 32 and 210 . 4 and first and 10 % and 10 . 5 % and 425 - 555 - 1234 and 3 degrees and - 27 . 5 degrees c and the next one and the previous one", + "score": 0.9074669, + "startIndex": 0, + "type": "Composite1" + }, + { + "endIndex": 1, + "entity": "12", + "resolution": { + "subtype": "integer", + "value": "12" + }, + "startIndex": 0, + "type": "builtin.number" + }, + { + "endIndex": 17, + "entity": "3", + "resolution": { + "subtype": "integer", + "value": "3" + }, + "startIndex": 17, + "type": "builtin.number" + }, + { + "endIndex": 52, + "entity": "2019", + "resolution": { + "subtype": "integer", + "value": "2019" + }, + "startIndex": 49, + "type": "builtin.number" + }, + { + "endIndex": 91, + "entity": "5", + "resolution": { + "subtype": "integer", + "value": "5" + }, + "startIndex": 91, + "type": "builtin.number" + }, + { + "endIndex": 102, + "entity": "4", + "resolution": { + "subtype": "integer", + "value": "4" + }, + "startIndex": 102, + "type": "builtin.number" + }, + { + "endIndex": 114, + "entity": "4", + "resolution": { + "subtype": "integer", + "value": "4" + }, + "startIndex": 114, + "type": "builtin.number" + }, + { + "endIndex": 156, + "entity": "4", + "resolution": { + "subtype": "integer", + "value": "4" + }, + "startIndex": 156, + "type": "builtin.number" + }, + { + "endIndex": 166, + "entity": "4.25", + "resolution": { + "subtype": "decimal", + "value": "4.25" + }, + "startIndex": 163, + "type": "builtin.number" + }, + { + "endIndex": 178, + "entity": "32", + "resolution": { + "subtype": "integer", + "value": "32" + }, + "startIndex": 177, + "type": "builtin.number" + }, + { + "endIndex": 188, + "entity": "210.4", + "resolution": { + "subtype": "decimal", + "value": "210.4" + }, + "startIndex": 184, + "type": "builtin.number" + }, + { + "endIndex": 205, + "entity": "10", + "resolution": { + "subtype": "integer", + "value": "10" + }, + "startIndex": 204, + "type": "builtin.number" + }, + { + "endIndex": 215, + "entity": "10.5", + "resolution": { + "subtype": "decimal", + "value": "10.5" + }, + "startIndex": 212, + "type": "builtin.number" + }, + { + "endIndex": 224, + "entity": "425", + "resolution": { + "subtype": "integer", + "value": "425" + }, + "startIndex": 222, + "type": "builtin.number" + }, + { + "endIndex": 228, + "entity": "555", + "resolution": { + "subtype": "integer", + "value": "555" + }, + "startIndex": 226, + "type": "builtin.number" + }, + { + "endIndex": 233, + "entity": "1234", + "resolution": { + "subtype": "integer", + "value": "1234" + }, + "startIndex": 230, + "type": "builtin.number" + }, + { + "endIndex": 239, + "entity": "3", + "resolution": { + "subtype": "integer", + "value": "3" + }, + "startIndex": 239, + "type": "builtin.number" + }, + { + "endIndex": 257, + "entity": "-27.5", + "resolution": { + "subtype": "decimal", + "value": "-27.5" + }, + "startIndex": 253, + "type": "builtin.number" + }, + { + "endIndex": 284, + "entity": "one", + "resolution": { + "subtype": "integer", + "value": "1" + }, + "startIndex": 282, + "type": "builtin.number" + }, + { + "endIndex": 305, + "entity": "one", + "resolution": { + "subtype": "integer", + "value": "1" + }, + "startIndex": 303, + "type": "builtin.number" + }, + { + "endIndex": 11, + "entity": "12 years old", + "resolution": { + "unit": "Year", + "value": "12" + }, + "role": "begin", + "startIndex": 0, + "type": "builtin.age" + }, + { + "endIndex": 26, + "entity": "3 days old", + "resolution": { + "unit": "Day", + "value": "3" + }, + "role": "end", + "startIndex": 17, + "type": "builtin.age" + }, + { + "endIndex": 7, + "entity": "12 years", + "resolution": { + "values": [ + { + "timex": "P12Y", + "type": "duration", + "value": "378432000" + } + ] + }, + "startIndex": 0, + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 22, + "entity": "3 days", + "resolution": { + "values": [ + { + "timex": "P3D", + "type": "duration", + "value": "259200" + } + ] + }, + "startIndex": 17, + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 52, + "entity": "monday july 3rd, 2019", + "resolution": { + "values": [ + { + "timex": "2019-07-03", + "type": "date", + "value": "2019-07-03" + } + ] + }, + "startIndex": 32, + "type": "builtin.datetimeV2.date" + }, + { + "endIndex": 69, + "entity": "every monday", + "resolution": { + "values": [ + { + "timex": "XXXX-WXX-1", + "type": "set", + "value": "not resolved" + } + ] + }, + "startIndex": 58, + "type": "builtin.datetimeV2.set" + }, + { + "endIndex": 96, + "entity": "between 3am and 5:30am", + "resolution": { + "values": [ + { + "end": "05:30:00", + "start": "03:00:00", + "timex": "(T03,T05:30,PT2H30M)", + "type": "timerange" + } + ] + }, + "startIndex": 75, + "type": "builtin.datetimeV2.timerange" + }, + { + "endIndex": 108, + "entity": "4 acres", + "resolution": { + "unit": "Acre", + "value": "4" + }, + "startIndex": 102, + "type": "builtin.dimension" + }, + { + "endIndex": 126, + "entity": "4 pico meters", + "resolution": { + "unit": "Picometer", + "value": "4" + }, + "startIndex": 114, + "type": "builtin.dimension" + }, + { + "endIndex": 149, + "entity": "chrimc@hotmail.com", + "resolution": { + "value": "chrimc@hotmail.com" + }, + "startIndex": 132, + "type": "builtin.email" + }, + { + "endIndex": 156, + "entity": "$4", + "resolution": { + "unit": "Dollar", + "value": "4" + }, + "startIndex": 155, + "type": "builtin.currency" + }, + { + "endIndex": 166, + "entity": "$4.25", + "resolution": { + "unit": "Dollar", + "value": "4.25" + }, + "role": "max", + "startIndex": 162, + "type": "builtin.currency" + }, + { + "endIndex": 46, + "entity": "3rd", + "resolution": { + "offset": "3", + "relativeTo": "start" + }, + "role": "endpos", + "startIndex": 44, + "type": "builtin.ordinalV2" + }, + { + "endIndex": 198, + "entity": "first", + "resolution": { + "offset": "1", + "relativeTo": "start" + }, + "startIndex": 194, + "type": "builtin.ordinalV2" + }, + { + "endIndex": 284, + "entity": "next one", + "resolution": { + "offset": "1", + "relativeTo": "current" + }, + "startIndex": 277, + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 305, + "entity": "previous one", + "resolution": { + "offset": "-1", + "relativeTo": "current" + }, + "startIndex": 294, + "type": "builtin.ordinalV2.relative" + }, + { + "endIndex": 206, + "entity": "10%", + "resolution": { + "value": "10%" + }, + "startIndex": 204, + "type": "builtin.percentage" + }, + { + "endIndex": 216, + "entity": "10.5%", + "resolution": { + "value": "10.5%" + }, + "startIndex": 212, + "type": "builtin.percentage" + }, + { + "endIndex": 233, + "entity": "425-555-1234", + "resolution": { + "score": "0.9", + "value": "425-555-1234" + }, + "startIndex": 222, + "type": "builtin.phonenumber" + }, + { + "endIndex": 247, + "entity": "3 degrees", + "resolution": { + "unit": "Degree", + "value": "3" + }, + "startIndex": 239, + "type": "builtin.temperature" + }, + { + "endIndex": 267, + "entity": "-27.5 degrees c", + "resolution": { + "unit": "C", + "value": "-27.5" + }, + "startIndex": 253, + "type": "builtin.temperature" + } + ], + "intents": [ + { + "intent": "EntityTests", + "score": 0.958614767 + }, + { + "intent": "Roles", + "score": 0.191202149 + }, + { + "intent": "Weather.GetForecast", + "score": 0.0141556319 + }, + { + "intent": "None", + "score": 0.0101076821 + }, + { + "intent": "search", + "score": 0.00475360872 + }, + { + "intent": "Travel", + "score": 0.00232480234 + }, + { + "intent": "Delivery", + "score": 0.000280677923 + }, + { + "intent": "SpecifyName", + "score": 7.367716E-05 + }, + { + "intent": "Help", + "score": 4.74059061E-06 + }, + { + "intent": "Cancel", + "score": 1.54311692E-06 + }, + { + "intent": "Greeting", + "score": 8.076372E-07 + } + ], + "query": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "EntityTests", + "score": 0.958614767 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "begin": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "begin", + "startIndex": 0, + "text": "12 years old", + "type": "builtin.age" + } + ], + "Composite1": [ + { + "length": 306, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one", + "type": "Composite1" + } + ], + "end": [ + { + "length": 10, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "end", + "startIndex": 17, + "text": "3 days old", + "type": "builtin.age" + } + ], + "endpos": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "endpos", + "startIndex": 44, + "text": "3rd", + "type": "builtin.ordinalV2" + } + ], + "max": [ + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "max", + "startIndex": 162, + "text": "$4.25", + "type": "builtin.currency" + } + ], + "ordinalV2": [ + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 194, + "text": "first", + "type": "builtin.ordinalV2" + }, + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 277, + "text": "next one", + "type": "builtin.ordinalV2.relative" + }, + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 294, + "text": "previous one", + "type": "builtin.ordinalV2.relative" + } + ] + }, + "begin": [ + { + "number": 12, + "units": "Year" + } + ], + "Composite1": [ + { + "$instance": { + "datetimeV2": [ + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12 years", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 6, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3 days", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 21, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 32, + "text": "monday july 3rd, 2019", + "type": "builtin.datetimeV2.date" + }, + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 58, + "text": "every monday", + "type": "builtin.datetimeV2.set" + }, + { + "length": 22, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 75, + "text": "between 3am and 5:30am", + "type": "builtin.datetimeV2.timerange" + } + ], + "dimension": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4 acres", + "type": "builtin.dimension" + }, + { + "length": 13, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4 pico meters", + "type": "builtin.dimension" + } + ], + "email": [ + { + "length": 18, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 132, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "money": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 155, + "text": "$4", + "type": "builtin.currency" + } + ], + "number": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "12", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "3", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 49, + "text": "2019", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 91, + "text": "5", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 102, + "text": "4", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 114, + "text": "4", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "4", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 163, + "text": "4.25", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 177, + "text": "32", + "type": "builtin.number" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 184, + "text": "210.4", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 222, + "text": "425", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "555", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 230, + "text": "1234", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3", + "type": "builtin.number" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 282, + "text": "one", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 303, + "text": "one", + "type": "builtin.number" + } + ], + "percentage": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 204, + "text": "10%", + "type": "builtin.percentage" + }, + { + "length": 5, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "10.5%", + "type": "builtin.percentage" + } + ], + "phonenumber": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 222, + "text": "425-555-1234", + "type": "builtin.phonenumber" + } + ], + "temperature": [ + { + "length": 9, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 239, + "text": "3 degrees", + "type": "builtin.temperature" + }, + { + "length": 15, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 253, + "text": "-27.5 degrees c", + "type": "builtin.temperature" + } + ] + }, + "datetimeV2": [ + { + "type": "duration", + "values": [ + { + "resolution": [ + { + "value": "378432000" + } + ], + "timex": "P12Y" + } + ] + }, + { + "type": "duration", + "values": [ + { + "resolution": [ + { + "value": "259200" + } + ], + "timex": "P3D" + } + ] + }, + { + "type": "date", + "values": [ + { + "resolution": [ + { + "value": "2019-07-03" + } + ], + "timex": "2019-07-03" + } + ] + }, + { + "type": "set", + "values": [ + { + "resolution": [ + { + "value": "not resolved" + } + ], + "timex": "XXXX-WXX-1" + } + ] + }, + { + "type": "timerange", + "values": [ + { + "resolution": [ + { + "end": "05:30:00", + "start": "03:00:00" + } + ], + "timex": "(T03,T05:30,PT2H30M)" + } + ] + } + ], + "dimension": [ + { + "number": 4, + "units": "Acre" + }, + { + "number": 4, + "units": "Picometer" + } + ], + "email": [ + "chrimc@hotmail.com" + ], + "money": [ + { + "number": 4, + "units": "Dollar" + } + ], + "number": [ + 12, + 3, + 2019, + 5, + 4, + 4, + 4, + 4.25, + 32, + 210.4, + 10, + 10.5, + 425, + 555, + 1234, + 3, + -27.5, + 1, + 1 + ], + "percentage": [ + 10, + 10.5 + ], + "phonenumber": [ + "425-555-1234" + ], + "temperature": [ + { + "number": 3, + "units": "Degree" + }, + { + "number": -27.5, + "units": "C" + } + ] + } + ], + "end": [ + { + "number": 3, + "units": "Day" + } + ], + "endpos": [ + { + "offset": 3, + "relativeTo": "start" + } + ], + "max": [ + { + "number": 4.25, + "units": "Dollar" + } + ], + "ordinalV2": [ + { + "offset": 1, + "relativeTo": "start" + }, + { + "offset": 1, + "relativeTo": "current" + }, + { + "offset": -1, + "relativeTo": "current" + } + ] + }, + "intents": { + "Cancel": { + "score": 1.54311692E-06 + }, + "Delivery": { + "score": 0.000280677923 + }, + "EntityTests": { + "score": 0.958614767 + }, + "Greeting": { + "score": 8.076372E-07 + }, + "Help": { + "score": 4.74059061E-06 + }, + "None": { + "score": 0.0101076821 + }, + "Roles": { + "score": 0.191202149 + }, + "search": { + "score": 0.00475360872 + }, + "SpecifyName": { + "score": 7.367716E-05 + }, + "Travel": { + "score": 0.00232480234 + }, + "Weather.GetForecast": { + "score": 0.0141556319 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "EntityTests" + }, + "query": "12 years old and 3 days old and monday july 3rd, 2019 and every monday and between 3am and 5:30am and 4 acres and 4 pico meters and chrimc@hotmail.com and $4 and $4.25 and also 32 and 210.4 and first and 10% and 10.5% and 425-555-1234 and 3 degrees and -27.5 degrees c and the next one and the previous one" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TypedPrebuilt.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TypedPrebuilt.json new file mode 100644 index 000000000..1ccad7581 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TypedPrebuilt.json @@ -0,0 +1,351 @@ +{ + "entities": { + "$instance": { + "Composite2": [ + { + "endIndex": 66, + "modelType": "Composite Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com is where you can get a weather forecast for seattle", + "type": "Composite2" + } + ], + "geographyV2": [ + { + "endIndex": 66, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "builtin.geographyV2.city" + } + ], + "oldURL": [ + { + "endIndex": 14, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com", + "type": "builtin.url" + } + ] + }, + "Composite2": [ + { + "$instance": { + "Weather_Location": [ + { + "endIndex": 66, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "Weather.Location" + } + ] + }, + "Weather_Location": [ + "seattle" + ] + } + ], + "geographyV2": [ + { + "location": "seattle", + "type": "city" + } + ], + "oldURL": [ + "http://foo.com" + ] + }, + "intents": { + "Cancel": { + "score": 0.00017013021 + }, + "Delivery": { + "score": 0.00114031672 + }, + "EntityTests": { + "score": 0.286522 + }, + "Greeting": { + "score": 0.000150978623 + }, + "Help": { + "score": 0.000547617 + }, + "None": { + "score": 0.01798658 + }, + "Roles": { + "score": 0.0459664278 + }, + "search": { + "score": 0.0009428267 + }, + "SpecifyName": { + "score": 0.0009960134 + }, + "Travel": { + "score": 0.00235179346 + }, + "Weather_GetForecast": { + "score": 0.6732952 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "http://foo.com is where you can get a weather forecast for seattle", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "compositeEntities": [ + { + "children": [ + { + "type": "Weather.Location", + "value": "seattle" + } + ], + "parentType": "Composite2", + "value": "http : / / foo . com is where you can get a weather forecast for seattle" + } + ], + "entities": [ + { + "endIndex": 65, + "entity": "seattle", + "score": 0.8245291, + "startIndex": 59, + "type": "Weather.Location" + }, + { + "endIndex": 65, + "entity": "http : / / foo . com is where you can get a weather forecast for seattle", + "score": 0.6503277, + "startIndex": 0, + "type": "Composite2" + }, + { + "endIndex": 65, + "entity": "seattle", + "startIndex": 59, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 13, + "entity": "http://foo.com", + "resolution": { + "value": "http://foo.com" + }, + "role": "oldURL", + "startIndex": 0, + "type": "builtin.url" + } + ], + "intents": [ + { + "intent": "Weather.GetForecast", + "score": 0.6732952 + }, + { + "intent": "EntityTests", + "score": 0.286522 + }, + { + "intent": "Roles", + "score": 0.0459664278 + }, + { + "intent": "None", + "score": 0.01798658 + }, + { + "intent": "Travel", + "score": 0.00235179346 + }, + { + "intent": "Delivery", + "score": 0.00114031672 + }, + { + "intent": "SpecifyName", + "score": 0.0009960134 + }, + { + "intent": "search", + "score": 0.0009428267 + }, + { + "intent": "Help", + "score": 0.000547617 + }, + { + "intent": "Cancel", + "score": 0.00017013021 + }, + { + "intent": "Greeting", + "score": 0.000150978623 + } + ], + "query": "http://foo.com is where you can get a weather forecast for seattle", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "Weather.GetForecast", + "score": 0.6732952 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "Composite2": [ + { + "length": 66, + "modelType": "Composite Entity Extractor", + "modelTypeId": 4, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "http://foo.com is where you can get a weather forecast for seattle", + "type": "Composite2" + } + ], + "geographyV2": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "builtin.geographyV2.city" + } + ], + "oldURL": [ + { + "length": 14, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "oldURL", + "startIndex": 0, + "text": "http://foo.com", + "type": "builtin.url" + } + ] + }, + "Composite2": [ + { + "$instance": { + "Weather.Location": [ + { + "length": 7, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "startIndex": 59, + "text": "seattle", + "type": "Weather.Location" + } + ] + }, + "Weather.Location": [ + "seattle" + ] + } + ], + "geographyV2": [ + { + "type": "city", + "value": "seattle" + } + ], + "oldURL": [ + "http://foo.com" + ] + }, + "intents": { + "Cancel": { + "score": 0.00017013021 + }, + "Delivery": { + "score": 0.00114031672 + }, + "EntityTests": { + "score": 0.286522 + }, + "Greeting": { + "score": 0.000150978623 + }, + "Help": { + "score": 0.000547617 + }, + "None": { + "score": 0.01798658 + }, + "Roles": { + "score": 0.0459664278 + }, + "search": { + "score": 0.0009428267 + }, + "SpecifyName": { + "score": 0.0009960134 + }, + "Travel": { + "score": 0.00235179346 + }, + "Weather.GetForecast": { + "score": 0.6732952 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Weather.GetForecast" + }, + "query": "http://foo.com is where you can get a weather forecast for seattle" + } + } +} diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/V1DatetimeResolution.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/V1DatetimeResolution.json new file mode 100644 index 000000000..eb662c3ff --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/V1DatetimeResolution.json @@ -0,0 +1,19 @@ +{ + "query": "4", + "topScoringIntent": { + "intent": "None", + "score": 0.8575135 + }, + "entities": [ + { + "entity": "4", + "type": "builtin.datetime.time", + "startIndex": 0, + "endIndex": 0, + "resolution": { + "comment": "ampm", + "time": "T04" + } + } + ] +} \ No newline at end of file diff --git a/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/roles.json b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/roles.json new file mode 100644 index 000000000..adb7c1fa6 --- /dev/null +++ b/libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/roles.json @@ -0,0 +1,2252 @@ +{ + "entities": { + "$instance": { + "a": [ + { + "endIndex": 309, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 299, + "text": "68 degrees", + "type": "builtin.temperature" + } + ], + "arrive": [ + { + "endIndex": 373, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 370, + "text": "5pm", + "type": "builtin.datetimeV2.time" + } + ], + "b": [ + { + "endIndex": 324, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 314, + "text": "72 degrees", + "type": "builtin.temperature" + } + ], + "begin": [ + { + "endIndex": 76, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 65, + "text": "6 years old", + "type": "builtin.age" + } + ], + "buy": [ + { + "endIndex": 124, + "modelType": "Regex Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 119, + "text": "kb922", + "type": "Part" + } + ], + "Buyer": [ + { + "endIndex": 178, + "modelType": "List Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 173, + "text": "delta", + "type": "Airline" + } + ], + "datetime": [ + { + "endIndex": 72, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 65, + "text": "6 years", + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 88, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 81, + "text": "8 years", + "type": "builtin.datetimeV2.duration" + } + ], + "destination": [ + { + "endIndex": 233, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "redmond", + "type": "Weather.Location" + } + ], + "dimension": [ + { + "endIndex": 358, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 355, + "text": "3pm", + "type": "builtin.dimension" + }, + { + "endIndex": 373, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 370, + "text": "5pm", + "type": "builtin.dimension" + } + ], + "end": [ + { + "endIndex": 92, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 81, + "text": "8 years old", + "type": "builtin.age" + } + ], + "geographyV2": [ + { + "endIndex": 218, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "hawaii", + "type": "builtin.geographyV2.state" + }, + { + "endIndex": 233, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "redmond", + "type": "builtin.geographyV2.city" + } + ], + "leave": [ + { + "endIndex": 358, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 355, + "text": "3pm", + "type": "builtin.datetimeV2.time" + } + ], + "length": [ + { + "endIndex": 8, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "3 inches", + "type": "builtin.dimension" + } + ], + "likee": [ + { + "endIndex": 344, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 340, + "text": "mary", + "type": "Name" + } + ], + "liker": [ + { + "endIndex": 333, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 329, + "text": "john", + "type": "Name" + } + ], + "max": [ + { + "endIndex": 403, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 399, + "text": "$500", + "type": "builtin.currency" + } + ], + "maximum": [ + { + "endIndex": 44, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "10%", + "type": "builtin.percentage" + } + ], + "min": [ + { + "endIndex": 394, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 390, + "text": "$400", + "type": "builtin.currency" + } + ], + "minimum": [ + { + "endIndex": 37, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 35, + "text": "5%", + "type": "builtin.percentage" + } + ], + "newPhone": [ + { + "endIndex": 164, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 152, + "text": "206-666-4123", + "type": "builtin.phonenumber" + } + ], + "number": [ + { + "endIndex": 1, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "3", + "type": "builtin.number" + }, + { + "endIndex": 18, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "2", + "type": "builtin.number" + }, + { + "endIndex": 36, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 35, + "text": "5", + "type": "builtin.number" + }, + { + "endIndex": 43, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "10", + "type": "builtin.number" + }, + { + "endIndex": 66, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 65, + "text": "6", + "type": "builtin.number" + }, + { + "endIndex": 82, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 81, + "text": "8", + "type": "builtin.number" + }, + { + "endIndex": 139, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 136, + "text": "425", + "type": "builtin.number" + }, + { + "endIndex": 143, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 140, + "text": "777", + "type": "builtin.number" + }, + { + "endIndex": 148, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 144, + "text": "1212", + "type": "builtin.number" + }, + { + "endIndex": 155, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 152, + "text": "206", + "type": "builtin.number" + }, + { + "endIndex": 159, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "666", + "type": "builtin.number" + }, + { + "endIndex": 164, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 160, + "text": "4123", + "type": "builtin.number" + }, + { + "endIndex": 301, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 299, + "text": "68", + "type": "builtin.number" + }, + { + "endIndex": 316, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 314, + "text": "72", + "type": "builtin.number" + }, + { + "endIndex": 394, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 391, + "text": "400", + "type": "builtin.number" + }, + { + "endIndex": 403, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 400, + "text": "500", + "type": "builtin.number" + } + ], + "old": [ + { + "endIndex": 148, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "score": 0.9, + "startIndex": 136, + "text": "425-777-1212", + "type": "builtin.phonenumber" + } + ], + "oldURL": [ + { + "endIndex": 252, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 238, + "text": "http://foo.com", + "type": "builtin.url" + } + ], + "personName": [ + { + "endIndex": 333, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 329, + "text": "john", + "type": "builtin.personName" + }, + { + "endIndex": 344, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 340, + "text": "mary", + "type": "builtin.personName" + } + ], + "receiver": [ + { + "endIndex": 431, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 413, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "sell": [ + { + "endIndex": 114, + "modelType": "Regex Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 109, + "text": "kb457", + "type": "Part" + } + ], + "Seller": [ + { + "endIndex": 189, + "modelType": "List Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 183, + "text": "virgin", + "type": "Airline" + } + ], + "sender": [ + { + "endIndex": 451, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 437, + "text": "emad@gmail.com", + "type": "builtin.email" + } + ], + "source": [ + { + "endIndex": 218, + "modelType": "Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "hawaii", + "type": "Weather.Location" + } + ], + "url": [ + { + "endIndex": 279, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 264, + "text": "http://blah.com", + "type": "builtin.url" + } + ], + "width": [ + { + "endIndex": 25, + "modelType": "Prebuilt Entity Extractor", + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "2 inches", + "type": "builtin.dimension" + } + ] + }, + "a": [ + { + "number": 68, + "units": "Degree" + } + ], + "arrive": [ + { + "timex": [ + "T17" + ], + "type": "time" + } + ], + "b": [ + { + "number": 72, + "units": "Degree" + } + ], + "begin": [ + { + "number": 6, + "units": "Year" + } + ], + "buy": [ + "kb922" + ], + "Buyer": [ + [ + "Delta" + ] + ], + "datetime": [ + { + "timex": [ + "P6Y" + ], + "type": "duration" + }, + { + "timex": [ + "P8Y" + ], + "type": "duration" + } + ], + "destination": [ + "redmond" + ], + "dimension": [ + { + "number": 3, + "units": "Picometer" + }, + { + "number": 5, + "units": "Picometer" + } + ], + "end": [ + { + "number": 8, + "units": "Year" + } + ], + "geographyV2": [ + { + "location": "hawaii", + "type": "state" + }, + { + "location": "redmond", + "type": "city" + } + ], + "leave": [ + { + "timex": [ + "T15" + ], + "type": "time" + } + ], + "length": [ + { + "number": 3, + "units": "Inch" + } + ], + "likee": [ + "mary" + ], + "liker": [ + "john" + ], + "max": [ + { + "number": 500, + "units": "Dollar" + } + ], + "maximum": [ + 10 + ], + "min": [ + { + "number": 400, + "units": "Dollar" + } + ], + "minimum": [ + 5 + ], + "newPhone": [ + "206-666-4123" + ], + "number": [ + 3, + 2, + 5, + 10, + 6, + 8, + 425, + 777, + 1212, + 206, + 666, + 4123, + 68, + 72, + 400, + 500 + ], + "old": [ + "425-777-1212" + ], + "oldURL": [ + "http://foo.com" + ], + "personName": [ + "john", + "mary" + ], + "receiver": [ + "chrimc@hotmail.com" + ], + "sell": [ + "kb457" + ], + "Seller": [ + [ + "Virgin" + ] + ], + "sender": [ + "emad@gmail.com" + ], + "source": [ + "hawaii" + ], + "url": [ + "http://blah.com" + ], + "width": [ + { + "number": 2, + "units": "Inch" + } + ] + }, + "intents": { + "Cancel": { + "score": 4.48137826E-07 + }, + "Delivery": { + "score": 7.920229E-05 + }, + "EntityTests": { + "score": 0.00420103827 + }, + "Greeting": { + "score": 4.6571725E-07 + }, + "Help": { + "score": 7.5179554E-07 + }, + "None": { + "score": 0.0009303715 + }, + "Roles": { + "score": 1.0 + }, + "search": { + "score": 0.00245359377 + }, + "SpecifyName": { + "score": 5.62756977E-05 + }, + "Travel": { + "score": 0.002153493 + }, + "Weather_GetForecast": { + "score": 0.0100878729 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "text": "3 inches long by 2 inches wide and 5% to 10% and are you between 6 years old and 8 years old and can i trade kb457 for kb922 and change 425-777-1212 to 206-666-4123 and did delta buy virgin and did the rain from hawaii get to redmond and http://foo.com changed to http://blah.com and i like between 68 degrees and 72 degrees and john likes mary and leave 3pm and arrive 5pm and pay between $400 and $500 and send chrimc@hotmail.com from emad@gmail.com", + "v2": { + "options": { + "IncludeAllIntents": true, + "IncludeInstanceData": true, + "LogPersonalInformation": false, + "Timeout": 100000.0 + }, + "response": { + "entities": [ + { + "endIndex": 332, + "entity": "john", + "role": "liker", + "score": 0.991758049, + "startIndex": 329, + "type": "Name" + }, + { + "endIndex": 343, + "entity": "mary", + "role": "likee", + "score": 0.995282352, + "startIndex": 340, + "type": "Name" + }, + { + "endIndex": 217, + "entity": "hawaii", + "role": "source", + "score": 0.985036731, + "startIndex": 212, + "type": "Weather.Location" + }, + { + "endIndex": 232, + "entity": "redmond", + "role": "destination", + "score": 0.989005446, + "startIndex": 226, + "type": "Weather.Location" + }, + { + "endIndex": 0, + "entity": "3", + "resolution": { + "subtype": "integer", + "value": "3" + }, + "startIndex": 0, + "type": "builtin.number" + }, + { + "endIndex": 17, + "entity": "2", + "resolution": { + "subtype": "integer", + "value": "2" + }, + "startIndex": 17, + "type": "builtin.number" + }, + { + "endIndex": 35, + "entity": "5", + "resolution": { + "subtype": "integer", + "value": "5" + }, + "startIndex": 35, + "type": "builtin.number" + }, + { + "endIndex": 42, + "entity": "10", + "resolution": { + "subtype": "integer", + "value": "10" + }, + "startIndex": 41, + "type": "builtin.number" + }, + { + "endIndex": 65, + "entity": "6", + "resolution": { + "subtype": "integer", + "value": "6" + }, + "startIndex": 65, + "type": "builtin.number" + }, + { + "endIndex": 81, + "entity": "8", + "resolution": { + "subtype": "integer", + "value": "8" + }, + "startIndex": 81, + "type": "builtin.number" + }, + { + "endIndex": 138, + "entity": "425", + "resolution": { + "subtype": "integer", + "value": "425" + }, + "startIndex": 136, + "type": "builtin.number" + }, + { + "endIndex": 142, + "entity": "777", + "resolution": { + "subtype": "integer", + "value": "777" + }, + "startIndex": 140, + "type": "builtin.number" + }, + { + "endIndex": 147, + "entity": "1212", + "resolution": { + "subtype": "integer", + "value": "1212" + }, + "startIndex": 144, + "type": "builtin.number" + }, + { + "endIndex": 154, + "entity": "206", + "resolution": { + "subtype": "integer", + "value": "206" + }, + "startIndex": 152, + "type": "builtin.number" + }, + { + "endIndex": 158, + "entity": "666", + "resolution": { + "subtype": "integer", + "value": "666" + }, + "startIndex": 156, + "type": "builtin.number" + }, + { + "endIndex": 163, + "entity": "4123", + "resolution": { + "subtype": "integer", + "value": "4123" + }, + "startIndex": 160, + "type": "builtin.number" + }, + { + "endIndex": 300, + "entity": "68", + "resolution": { + "subtype": "integer", + "value": "68" + }, + "startIndex": 299, + "type": "builtin.number" + }, + { + "endIndex": 315, + "entity": "72", + "resolution": { + "subtype": "integer", + "value": "72" + }, + "startIndex": 314, + "type": "builtin.number" + }, + { + "endIndex": 393, + "entity": "400", + "resolution": { + "subtype": "integer", + "value": "400" + }, + "startIndex": 391, + "type": "builtin.number" + }, + { + "endIndex": 402, + "entity": "500", + "resolution": { + "subtype": "integer", + "value": "500" + }, + "startIndex": 400, + "type": "builtin.number" + }, + { + "endIndex": 75, + "entity": "6 years old", + "resolution": { + "unit": "Year", + "value": "6" + }, + "role": "begin", + "startIndex": 65, + "type": "builtin.age" + }, + { + "endIndex": 91, + "entity": "8 years old", + "resolution": { + "unit": "Year", + "value": "8" + }, + "role": "end", + "startIndex": 81, + "type": "builtin.age" + }, + { + "endIndex": 71, + "entity": "6 years", + "resolution": { + "values": [ + { + "timex": "P6Y", + "type": "duration", + "value": "189216000" + } + ] + }, + "startIndex": 65, + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 87, + "entity": "8 years", + "resolution": { + "values": [ + { + "timex": "P8Y", + "type": "duration", + "value": "252288000" + } + ] + }, + "startIndex": 81, + "type": "builtin.datetimeV2.duration" + }, + { + "endIndex": 357, + "entity": "3pm", + "resolution": { + "values": [ + { + "timex": "T15", + "type": "time", + "value": "15:00:00" + } + ] + }, + "role": "leave", + "startIndex": 355, + "type": "builtin.datetimeV2.time" + }, + { + "endIndex": 372, + "entity": "5pm", + "resolution": { + "values": [ + { + "timex": "T17", + "type": "time", + "value": "17:00:00" + } + ] + }, + "role": "arrive", + "startIndex": 370, + "type": "builtin.datetimeV2.time" + }, + { + "endIndex": 7, + "entity": "3 inches", + "resolution": { + "unit": "Inch", + "value": "3" + }, + "role": "length", + "startIndex": 0, + "type": "builtin.dimension" + }, + { + "endIndex": 24, + "entity": "2 inches", + "resolution": { + "unit": "Inch", + "value": "2" + }, + "role": "width", + "startIndex": 17, + "type": "builtin.dimension" + }, + { + "endIndex": 357, + "entity": "3pm", + "resolution": { + "unit": "Picometer", + "value": "3" + }, + "startIndex": 355, + "type": "builtin.dimension" + }, + { + "endIndex": 372, + "entity": "5pm", + "resolution": { + "unit": "Picometer", + "value": "5" + }, + "startIndex": 370, + "type": "builtin.dimension" + }, + { + "endIndex": 430, + "entity": "chrimc@hotmail.com", + "resolution": { + "value": "chrimc@hotmail.com" + }, + "role": "receiver", + "startIndex": 413, + "type": "builtin.email" + }, + { + "endIndex": 450, + "entity": "emad@gmail.com", + "resolution": { + "value": "emad@gmail.com" + }, + "role": "sender", + "startIndex": 437, + "type": "builtin.email" + }, + { + "endIndex": 217, + "entity": "hawaii", + "startIndex": 212, + "type": "builtin.geographyV2.state" + }, + { + "endIndex": 232, + "entity": "redmond", + "startIndex": 226, + "type": "builtin.geographyV2.city" + }, + { + "endIndex": 393, + "entity": "$400", + "resolution": { + "unit": "Dollar", + "value": "400" + }, + "role": "min", + "startIndex": 390, + "type": "builtin.currency" + }, + { + "endIndex": 402, + "entity": "$500", + "resolution": { + "unit": "Dollar", + "value": "500" + }, + "role": "max", + "startIndex": 399, + "type": "builtin.currency" + }, + { + "endIndex": 36, + "entity": "5%", + "resolution": { + "value": "5%" + }, + "role": "minimum", + "startIndex": 35, + "type": "builtin.percentage" + }, + { + "endIndex": 43, + "entity": "10%", + "resolution": { + "value": "10%" + }, + "role": "maximum", + "startIndex": 41, + "type": "builtin.percentage" + }, + { + "endIndex": 332, + "entity": "john", + "startIndex": 329, + "type": "builtin.personName" + }, + { + "endIndex": 343, + "entity": "mary", + "startIndex": 340, + "type": "builtin.personName" + }, + { + "endIndex": 147, + "entity": "425-777-1212", + "resolution": { + "score": "0.9", + "value": "425-777-1212" + }, + "role": "old", + "startIndex": 136, + "type": "builtin.phonenumber" + }, + { + "endIndex": 163, + "entity": "206-666-4123", + "resolution": { + "score": "0.9", + "value": "206-666-4123" + }, + "role": "newPhone", + "startIndex": 152, + "type": "builtin.phonenumber" + }, + { + "endIndex": 308, + "entity": "68 degrees", + "resolution": { + "unit": "Degree", + "value": "68" + }, + "role": "a", + "startIndex": 299, + "type": "builtin.temperature" + }, + { + "endIndex": 323, + "entity": "72 degrees", + "resolution": { + "unit": "Degree", + "value": "72" + }, + "role": "b", + "startIndex": 314, + "type": "builtin.temperature" + }, + { + "endIndex": 251, + "entity": "http://foo.com", + "resolution": { + "value": "http://foo.com" + }, + "role": "oldURL", + "startIndex": 238, + "type": "builtin.url" + }, + { + "endIndex": 278, + "entity": "http://blah.com", + "resolution": { + "value": "http://blah.com" + }, + "startIndex": 264, + "type": "builtin.url" + }, + { + "endIndex": 177, + "entity": "delta", + "resolution": { + "values": [ + "Delta" + ] + }, + "role": "Buyer", + "startIndex": 173, + "type": "Airline" + }, + { + "endIndex": 188, + "entity": "virgin", + "resolution": { + "values": [ + "Virgin" + ] + }, + "role": "Seller", + "startIndex": 183, + "type": "Airline" + }, + { + "endIndex": 113, + "entity": "kb457", + "role": "sell", + "startIndex": 109, + "type": "Part" + }, + { + "endIndex": 123, + "entity": "kb922", + "role": "buy", + "startIndex": 119, + "type": "Part" + } + ], + "intents": [ + { + "intent": "Roles", + "score": 1.0 + }, + { + "intent": "Weather.GetForecast", + "score": 0.0100878729 + }, + { + "intent": "EntityTests", + "score": 0.00420103827 + }, + { + "intent": "search", + "score": 0.00245359377 + }, + { + "intent": "Travel", + "score": 0.002153493 + }, + { + "intent": "None", + "score": 0.0009303715 + }, + { + "intent": "Delivery", + "score": 7.920229E-05 + }, + { + "intent": "SpecifyName", + "score": 5.62756977E-05 + }, + { + "intent": "Help", + "score": 7.5179554E-07 + }, + { + "intent": "Greeting", + "score": 4.6571725E-07 + }, + { + "intent": "Cancel", + "score": 4.48137826E-07 + } + ], + "query": "3 inches long by 2 inches wide and 5% to 10% and are you between 6 years old and 8 years old and can i trade kb457 for kb922 and change 425-777-1212 to 206-666-4123 and did delta buy virgin and did the rain from hawaii get to redmond and http://foo.com changed to http://blah.com and i like between 68 degrees and 72 degrees and john likes mary and leave 3pm and arrive 5pm and pay between $400 and $500 and send chrimc@hotmail.com from emad@gmail.com", + "sentimentAnalysis": { + "label": "neutral", + "score": 0.5 + }, + "topScoringIntent": { + "intent": "Roles", + "score": 1.0 + } + } + }, + "v3": { + "options": { + "IncludeAllIntents": true, + "IncludeAPIResults": true, + "IncludeInstanceData": true, + "Log": true, + "PreferExternalEntities": true, + "Slot": "production" + }, + "response": { + "prediction": { + "entities": { + "$instance": { + "a": [ + { + "length": 10, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "a", + "startIndex": 299, + "text": "68 degrees", + "type": "builtin.temperature" + } + ], + "arrive": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "arrive", + "startIndex": 370, + "text": "5pm", + "type": "builtin.datetimeV2.time" + } + ], + "b": [ + { + "length": 10, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "b", + "startIndex": 314, + "text": "72 degrees", + "type": "builtin.temperature" + } + ], + "begin": [ + { + "length": 11, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "begin", + "startIndex": 65, + "text": "6 years old", + "type": "builtin.age" + } + ], + "buy": [ + { + "length": 5, + "modelType": "Regex Entity Extractor", + "modelTypeId": 8, + "recognitionSources": [ + "model" + ], + "role": "buy", + "startIndex": 119, + "text": "kb922", + "type": "Part" + } + ], + "Buyer": [ + { + "length": 5, + "modelType": "List Entity Extractor", + "modelTypeId": 5, + "recognitionSources": [ + "model" + ], + "role": "Buyer", + "startIndex": 173, + "text": "delta", + "type": "Airline" + } + ], + "datetimeV2": [ + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 65, + "text": "6 years", + "type": "builtin.datetimeV2.duration" + }, + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 81, + "text": "8 years", + "type": "builtin.datetimeV2.duration" + } + ], + "destination": [ + { + "length": 7, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "role": "destination", + "startIndex": 226, + "text": "redmond", + "type": "Weather.Location" + } + ], + "dimension": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 355, + "text": "3pm", + "type": "builtin.dimension" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 370, + "text": "5pm", + "type": "builtin.dimension" + } + ], + "end": [ + { + "length": 11, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "end", + "startIndex": 81, + "text": "8 years old", + "type": "builtin.age" + } + ], + "geographyV2": [ + { + "length": 6, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 212, + "text": "hawaii", + "type": "builtin.geographyV2.state" + }, + { + "length": 7, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 226, + "text": "redmond", + "type": "builtin.geographyV2.city" + } + ], + "leave": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "leave", + "startIndex": 355, + "text": "3pm", + "type": "builtin.datetimeV2.time" + } + ], + "length": [ + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "length", + "startIndex": 0, + "text": "3 inches", + "type": "builtin.dimension" + } + ], + "likee": [ + { + "length": 4, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "role": "likee", + "startIndex": 340, + "text": "mary", + "type": "Name" + } + ], + "liker": [ + { + "length": 4, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "role": "liker", + "startIndex": 329, + "text": "john", + "type": "Name" + } + ], + "max": [ + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "max", + "startIndex": 399, + "text": "$500", + "type": "builtin.currency" + } + ], + "maximum": [ + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "maximum", + "startIndex": 41, + "text": "10%", + "type": "builtin.percentage" + } + ], + "min": [ + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "min", + "startIndex": 390, + "text": "$400", + "type": "builtin.currency" + } + ], + "minimum": [ + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "minimum", + "startIndex": 35, + "text": "5%", + "type": "builtin.percentage" + } + ], + "newPhone": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "newPhone", + "score": 0.9, + "startIndex": 152, + "text": "206-666-4123", + "type": "builtin.phonenumber" + } + ], + "number": [ + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 0, + "text": "3", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 17, + "text": "2", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 35, + "text": "5", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 41, + "text": "10", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 65, + "text": "6", + "type": "builtin.number" + }, + { + "length": 1, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 81, + "text": "8", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 136, + "text": "425", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 140, + "text": "777", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 144, + "text": "1212", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 152, + "text": "206", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 156, + "text": "666", + "type": "builtin.number" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 160, + "text": "4123", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 299, + "text": "68", + "type": "builtin.number" + }, + { + "length": 2, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 314, + "text": "72", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 391, + "text": "400", + "type": "builtin.number" + }, + { + "length": 3, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 400, + "text": "500", + "type": "builtin.number" + } + ], + "old": [ + { + "length": 12, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "old", + "score": 0.9, + "startIndex": 136, + "text": "425-777-1212", + "type": "builtin.phonenumber" + } + ], + "oldURL": [ + { + "length": 14, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "oldURL", + "startIndex": 238, + "text": "http://foo.com", + "type": "builtin.url" + } + ], + "personName": [ + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 329, + "text": "john", + "type": "builtin.personName" + }, + { + "length": 4, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 340, + "text": "mary", + "type": "builtin.personName" + } + ], + "receiver": [ + { + "length": 18, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "receiver", + "startIndex": 413, + "text": "chrimc@hotmail.com", + "type": "builtin.email" + } + ], + "sell": [ + { + "length": 5, + "modelType": "Regex Entity Extractor", + "modelTypeId": 8, + "recognitionSources": [ + "model" + ], + "role": "sell", + "startIndex": 109, + "text": "kb457", + "type": "Part" + } + ], + "Seller": [ + { + "length": 6, + "modelType": "List Entity Extractor", + "modelTypeId": 5, + "recognitionSources": [ + "model" + ], + "role": "Seller", + "startIndex": 183, + "text": "virgin", + "type": "Airline" + } + ], + "sender": [ + { + "length": 14, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "sender", + "startIndex": 437, + "text": "emad@gmail.com", + "type": "builtin.email" + } + ], + "source": [ + { + "length": 6, + "modelType": "Entity Extractor", + "modelTypeId": 1, + "recognitionSources": [ + "model" + ], + "role": "source", + "startIndex": 212, + "text": "hawaii", + "type": "Weather.Location" + } + ], + "url": [ + { + "length": 15, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "startIndex": 264, + "text": "http://blah.com", + "type": "builtin.url" + } + ], + "width": [ + { + "length": 8, + "modelType": "Prebuilt Entity Extractor", + "modelTypeId": 2, + "recognitionSources": [ + "model" + ], + "role": "width", + "startIndex": 17, + "text": "2 inches", + "type": "builtin.dimension" + } + ] + }, + "a": [ + { + "number": 68, + "units": "Degree" + } + ], + "arrive": [ + { + "type": "time", + "values": [ + { + "resolution": [ + { + "value": "17:00:00" + } + ], + "timex": "T17" + } + ] + } + ], + "b": [ + { + "number": 72, + "units": "Degree" + } + ], + "begin": [ + { + "number": 6, + "units": "Year" + } + ], + "buy": [ + "kb922" + ], + "Buyer": [ + [ + "Delta" + ] + ], + "datetimeV2": [ + { + "type": "duration", + "values": [ + { + "resolution": [ + { + "value": "189216000" + } + ], + "timex": "P6Y" + } + ] + }, + { + "type": "duration", + "values": [ + { + "resolution": [ + { + "value": "252288000" + } + ], + "timex": "P8Y" + } + ] + } + ], + "destination": [ + "redmond" + ], + "dimension": [ + { + "number": 3, + "units": "Picometer" + }, + { + "number": 5, + "units": "Picometer" + } + ], + "end": [ + { + "number": 8, + "units": "Year" + } + ], + "geographyV2": [ + { + "type": "state", + "value": "hawaii" + }, + { + "type": "city", + "value": "redmond" + } + ], + "leave": [ + { + "type": "time", + "values": [ + { + "resolution": [ + { + "value": "15:00:00" + } + ], + "timex": "T15" + } + ] + } + ], + "length": [ + { + "number": 3, + "units": "Inch" + } + ], + "likee": [ + "mary" + ], + "liker": [ + "john" + ], + "max": [ + { + "number": 500, + "units": "Dollar" + } + ], + "maximum": [ + 10 + ], + "min": [ + { + "number": 400, + "units": "Dollar" + } + ], + "minimum": [ + 5 + ], + "newPhone": [ + "206-666-4123" + ], + "number": [ + 3, + 2, + 5, + 10, + 6, + 8, + 425, + 777, + 1212, + 206, + 666, + 4123, + 68, + 72, + 400, + 500 + ], + "old": [ + "425-777-1212" + ], + "oldURL": [ + "http://foo.com" + ], + "personName": [ + "john", + "mary" + ], + "receiver": [ + "chrimc@hotmail.com" + ], + "sell": [ + "kb457" + ], + "Seller": [ + [ + "Virgin" + ] + ], + "sender": [ + "emad@gmail.com" + ], + "source": [ + "hawaii" + ], + "url": [ + "http://blah.com" + ], + "width": [ + { + "number": 2, + "units": "Inch" + } + ] + }, + "intents": { + "Cancel": { + "score": 4.48137826E-07 + }, + "Delivery": { + "score": 7.920229E-05 + }, + "EntityTests": { + "score": 0.00420103827 + }, + "Greeting": { + "score": 4.6571725E-07 + }, + "Help": { + "score": 7.5179554E-07 + }, + "None": { + "score": 0.0009303715 + }, + "Roles": { + "score": 1.0 + }, + "search": { + "score": 0.00245359377 + }, + "SpecifyName": { + "score": 5.62756977E-05 + }, + "Travel": { + "score": 0.002153493 + }, + "Weather.GetForecast": { + "score": 0.0100878729 + } + }, + "sentiment": { + "label": "neutral", + "score": 0.5 + }, + "topIntent": "Roles" + }, + "query": "3 inches long by 2 inches wide and 5% to 10% and are you between 6 years old and 8 years old and can i trade kb457 for kb922 and change 425-777-1212 to 206-666-4123 and did delta buy virgin and did the rain from hawaii get to redmond and http://foo.com changed to http://blah.com and i like between 68 degrees and 72 degrees and john likes mary and leave 3pm and arrive 5pm and pay between $400 and $500 and send chrimc@hotmail.com from emad@gmail.com" + } + } +} diff --git a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java index b0579d519..dbc459f98 100644 --- a/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java +++ b/libraries/bot-builder/src/main/java/com/microsoft/bot/builder/RecognizerResult.java @@ -33,6 +33,18 @@ public class RecognizerResult implements RecognizerConvert { */ private HashMap properties = new HashMap<>(); + /** + * Holds intent score info. + */ + @SuppressWarnings({ "checkstyle:VisibilityModifier" }) + public static class NamedIntentScore { + /// The intent name + public String intent; + + /// The intent score + public double score; + } + /** * Return the top scoring intent and its score. * @@ -40,16 +52,17 @@ public class RecognizerResult implements RecognizerConvert { * @throws IllegalArgumentException No intents available. */ @JsonIgnore - public IntentScore getTopScoringIntent() throws IllegalArgumentException { + public NamedIntentScore getTopScoringIntent() throws IllegalArgumentException { if (getIntents() == null) { throw new IllegalArgumentException("RecognizerResult.Intents cannot be null"); } - IntentScore topIntent = new IntentScore(); + NamedIntentScore topIntent = new NamedIntentScore(); for (Map.Entry intent : getIntents().entrySet()) { double score = intent.getValue().getScore(); - if (score > topIntent.getScore()) { - topIntent = intent.getValue(); + if (score > topIntent.score) { + topIntent.intent = intent.getKey(); + topIntent.score = intent.getValue().getScore(); } } diff --git a/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Recognizer.java b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Recognizer.java new file mode 100644 index 000000000..1861eb224 --- /dev/null +++ b/libraries/bot-dialogs/src/main/java/com/microsoft/bot/dialogs/Recognizer.java @@ -0,0 +1,272 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.bot.dialogs; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.microsoft.bot.builder.BotTelemetryClient; +import com.microsoft.bot.builder.IntentScore; +import com.microsoft.bot.builder.NullBotTelemetryClient; +import com.microsoft.bot.builder.RecognizerConvert; +import com.microsoft.bot.builder.RecognizerResult; +import com.microsoft.bot.connector.Async; +import com.microsoft.bot.schema.Activity; +import com.microsoft.bot.schema.Serialization; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * Recognizer base class. + * + *

Recognizers operate in a DialogContext environment to recognize user input into Intents + * and Entities.

+ * + *

+ * This class models 3 virtual methods around + * * Pure DialogContext (where the recognition happens against current state dialogcontext + * * Activity (where the recognition is from an Activity) + * * Text/Locale (where the recognition is from text/locale) + *

+ * + *

+ * The default implementation of DialogContext method is to use Context.Activity and call the + * activity method. + * The default implementation of Activity method is to filter to Message activities and pull + * out text/locale and call the text/locale method. + *

+ */ +public class Recognizer { + /** + * Intent name that will be produced by this recognizer if the child recognizers do not + * have consensus for intents. + */ + public static final String CHOOSE_INTENT = "ChooseIntent"; + + /** + * Standard none intent that means none of the recognizers recognize the intent. If each + * recognizer returns no intents or None intents, then this recognizer will return None intent. + */ + public static final String NONE_INTENT = "None"; + + @JsonProperty(value = "id") + private String id; + + @JsonIgnore + private BotTelemetryClient telemetryClient = new NullBotTelemetryClient(); + + /** + * Initializes a new Recognizer. + */ + public Recognizer() { + } + + /** + * Runs current DialogContext.TurnContext.Activity through a recognizer and returns a + * generic recognizer result. + * + * @param dialogContext Dialog Context. + * @param activity activity to recognize. + * @return Analysis of utterance. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity + ) { + return recognize(dialogContext, activity, null, null); + } + + /** + * Runs current DialogContext.TurnContext.Activity through a recognizer and returns a + * generic recognizer result. + * + * @param dialogContext Dialog Context. + * @param activity activity to recognize. + * @param telemetryProperties The properties to be included as part of the event tracking. + * @param telemetryMetrics The metrics to be included as part of the event tracking. + * @return Analysis of utterance. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + Map telemetryProperties, + Map telemetryMetrics + ) { + return Async.completeExceptionally(new NotImplementedException("recognize")); + } + + /** + * Runs current DialogContext.TurnContext.Activity through a recognizer and returns a + * strongly-typed recognizer result using RecognizerConvert. + * + * @param dialogContext Dialog Context. + * @param activity activity to recognize. + * @param telemetryProperties The properties to be included as part of the event tracking. + * @param telemetryMetrics The metrics to be included as part of the event tracking. + * @param c Class of type T. + * @param The RecognizerConvert. + * @return Analysis of utterance. + */ + public CompletableFuture recognize( + DialogContext dialogContext, + Activity activity, + Map telemetryProperties, + Map telemetryMetrics, + Class c + ) { + return Async.tryCompletable(() -> { + T result = c.newInstance(); + return recognize(dialogContext, activity, telemetryProperties, telemetryMetrics) + .thenApply(recognizerResult -> { + result.convert(recognizerResult); + return result; + }); + }); + } + + /** + * Returns ChooseIntent between multiple recognizer results. + * + * @param recognizerResults >recognizer Id => recognizer results map. + * @return recognizerResult which is ChooseIntent. + */ + protected static RecognizerResult createChooseIntentResult(Map recognizerResults) { + String text = null; + List candidates = new ArrayList<>(); + + for (Map.Entry recognizerResult : recognizerResults.entrySet()) { + text = recognizerResult.getValue().getText(); + RecognizerResult.NamedIntentScore top = recognizerResult.getValue().getTopScoringIntent(); + if (!StringUtils.equals(top.intent, NONE_INTENT)) { + ObjectNode candidate = Serialization.createObjectNode(); + candidate.put("id", recognizerResult.getKey()); + candidate.put("intent", top.intent); + candidate.put("score", top.score); + candidate.put("result", Serialization.objectToTree(recognizerResult.getValue())); + candidates.add(candidate); + } + } + + RecognizerResult result = new RecognizerResult(); + Map intents = new HashMap<>(); + + if (!candidates.isEmpty()) { + // return ChooseIntent with candidates array + intents.put(CHOOSE_INTENT, new IntentScore() {{ setScore(1.0); }}); + + result.setText(text); + result.setIntents(intents); + result.setProperties("candidates", Serialization.objectToTree(candidates)); + } else { + // just return a none intent + intents.put(NONE_INTENT, new IntentScore() {{ setScore(1.0); }}); + + result.setText(text); + result.setIntents(intents); + } + + return result; + } + + /** + * Gets id of the recognizer. + * @return id of the recognizer + */ + public String getId() { + return id; + } + + /** + * Sets id of the recognizer. + * @param withId id of the recognizer + */ + public void setId(String withId) { + id = withId; + } + + /** + * Gets the currently configured BotTelemetryClient that logs the RecognizerResult event. + * @return BotTelemetryClient + */ + public BotTelemetryClient getTelemetryClient() { + return telemetryClient; + } + + /** + * Sets the currently configured BotTelemetryClient that logs the RecognizerResult event. + * @param withTelemetryClient BotTelemetryClient + */ + public void setTelemetryClient(BotTelemetryClient withTelemetryClient) { + telemetryClient = withTelemetryClient; + } + + /** + * Uses the RecognizerResult to create a list of propeties to be included when tracking the + * result in telemetry. + * + * @param recognizerResult Recognizer Result. + * @param telemetryProperties A list of properties to append or override the properties + * created using the RecognizerResult. + * @param dialogContext >Dialog Context. + * @return A dictionary that can be included when calling the TrackEvent method on the + * TelemetryClient. + */ + protected Map fillRecognizerResultTelemetryProperties( + RecognizerResult recognizerResult, + Map telemetryProperties, + DialogContext dialogContext + ) { + Map properties = new HashMap<>(); + properties.put("Text", recognizerResult.getText()); + properties.put("AlteredText", recognizerResult.getAlteredText()); + properties.put("TopIntent", !recognizerResult.getIntents().isEmpty() + ? recognizerResult.getTopScoringIntent().intent : null); + properties.put("TopIntentScore", !recognizerResult.getIntents().isEmpty() + ? Double.toString(recognizerResult.getTopScoringIntent().score) : null); + properties.put("Intents", !recognizerResult.getIntents().isEmpty() + ? Serialization.toStringSilent(recognizerResult.getIntents()) : null); + properties.put("Entities", recognizerResult.getEntities() != null + ? Serialization.toStringSilent(recognizerResult.getEntities()) : null); + properties.put("AdditionalProperties", !recognizerResult.getProperties().isEmpty() + ? Serialization.toStringSilent(recognizerResult.getProperties()) : null); + + // Additional Properties can override "stock" properties. + if (telemetryProperties != null) { + properties.putAll(telemetryProperties); + } + + return properties; + } + + /** + * Tracks an event with the event name provided using the TelemetryClient attaching the + * properties / metrics. + * + * @param dialogContext Dialog Context. + * @param eventName The name of the event to track. + * @param telemetryProperties The properties to be included as part of the event tracking. + * @param telemetryMetrics The metrics to be included as part of the event tracking. + */ + protected void trackRecognizerResult( + DialogContext dialogContext, + String eventName, + Map telemetryProperties, + Map telemetryMetrics + ) { + if (telemetryClient instanceof NullBotTelemetryClient) { + BotTelemetryClient turnStateTelemetryClient = dialogContext.getContext() + .getTurnState().get(BotTelemetryClient.class); + telemetryClient = turnStateTelemetryClient != null ? turnStateTelemetryClient : telemetryClient; + } + + telemetryClient.trackEvent(eventName, telemetryProperties, telemetryMetrics); + } +} diff --git a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Serialization.java b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Serialization.java index 73f9466ec..53daaf4c8 100644 --- a/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Serialization.java +++ b/libraries/bot-schema/src/main/java/com/microsoft/bot/schema/Serialization.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -153,6 +154,21 @@ public static String toString(Object source) throws JsonProcessingException { return objectMapper.writeValueAsString(source); } + /** + * Convert an object to a JSON string. + * + * @param source The object to convert. + * @return The JSON string value. + * @throws JsonProcessingException Error converting to JSON + */ + public static String toStringSilent(Object source) { + try { + return objectMapper.writeValueAsString(source); + } catch (Throwable t) { + return null; + } + } + /** * Parses a JSON document. * @@ -235,5 +251,13 @@ public static JsonNode asNode(boolean b) { public static JsonNode asNode(byte b) { return objectMapper.getNodeFactory().numberNode(b); } + + /** + * Creates an ObjectNode. + * @return ObjectNode. + */ + public static ObjectNode createObjectNode() { + return objectMapper.createObjectNode(); + } }