Luis Recognizer package (#962)
* Adding first Iteration of Luis Recognizer * Adding tests, comments and fixing bugs * Enabling live testing, commenting Dialog Recognizer dependency * Removing spaces and fixing not implemented try catch * Fixing linting errors * Fixing style check errors * Fixing style checks * Adding package-info.java file * Adding missing Doc on Constructor * Adding missing javadoc at classes * Adding test on send trace Activity * Adding missing test * Added Dialogs Recognizer * Uncommented ExternalEntityRecognizer accessors * Added missing Dialog.Recognizer.recognize method * Adding test for DialogContext scenarios * Adding missing javadoc * Throwing Exception * Fixing style * Missing error message Co-authored-by: tracyboehrer <tracyboehrer@users.noreply.github.com>
This commit is contained in:
Родитель
497c35ee55
Коммит
c057023b61
|
@ -62,6 +62,38 @@
|
|||
<groupId>com.microsoft.bot</groupId>
|
||||
<artifactId>bot-applicationinsights</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.bot</groupId>
|
||||
<artifactId>bot-dialogs</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20190722</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<version>4.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.7.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
|
|
|
@ -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<ListElement> requestLists) {
|
||||
this.entity = entity;
|
||||
this.list = requestLists;
|
||||
}
|
||||
|
||||
@JsonProperty(value = "listEntityName")
|
||||
private String entity;
|
||||
|
||||
@JsonProperty(value = "requestLists")
|
||||
private List<ListElement> 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<ListElement> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the List.
|
||||
* @param list Element list of the Dynamic List.
|
||||
*/
|
||||
public void setList(List<ListElement> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<String> 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<String> 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<String> getSynonyms() {
|
||||
return synonyms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the synonyms of the canonical form.
|
||||
* @param synonyms List of synonyms of the canonical form.
|
||||
*/
|
||||
public void setSynonyms(List<String> 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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<String, IntentScore> 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<RecognizerResult> 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<RecognizerResult> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
TurnContext turnContext,
|
||||
Class<T> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
Class<T> 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<RecognizerResult> recognize(
|
||||
TurnContext turnContext,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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<RecognizerResult> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
TurnContext turnContext,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics,
|
||||
Class<T> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics,
|
||||
Class<T> 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<RecognizerResult> 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<RecognizerResult> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
TurnContext turnContext,
|
||||
LuisRecognizerOptions recognizerOptions,
|
||||
Class<T> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
LuisRecognizerOptions recognizerOptions,
|
||||
Class<T> 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<RecognizerResult> recognize(
|
||||
TurnContext turnContext,
|
||||
LuisRecognizerOptions recognizerOptions,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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<RecognizerResult> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
LuisRecognizerOptions recognizerOptions,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
TurnContext turnContext,
|
||||
LuisRecognizerOptions recognizerOptions,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics,
|
||||
Class<T> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
LuisRecognizerOptions recognizerOptions,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics,
|
||||
Class<T> 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<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics) {
|
||||
Map<String, String> properties = fillLuisEventPropertiesAsync(
|
||||
recognizerResult,
|
||||
turnContext,
|
||||
telemetryProperties);
|
||||
// Track the event
|
||||
this.getTelemetryClient().trackEvent(
|
||||
LuisTelemetryConstants.LUIS_RESULT,
|
||||
properties,
|
||||
telemetryMetrics);
|
||||
}
|
||||
|
||||
private Map<String, String> fillLuisEventPropertiesAsync(
|
||||
RecognizerResult recognizerResult,
|
||||
TurnContext turnContext,
|
||||
Map<String, String> telemetryProperties) {
|
||||
|
||||
Map<String, IntentScore> sortedIntents = sortIntents(recognizerResult);
|
||||
ArrayList<String> topTwoIntents = new ArrayList<>();
|
||||
Iterator<Map.Entry<String, IntentScore>> iterator = sortedIntents.entrySet().iterator();
|
||||
int intentCounter = 0;
|
||||
while (iterator.hasNext()
|
||||
&& intentCounter < 2) {
|
||||
intentCounter++;
|
||||
Map.Entry<String, IntentScore> intent = iterator.next();
|
||||
topTwoIntents.add(intent.getKey());
|
||||
}
|
||||
|
||||
// Add the intent score and conversation id properties
|
||||
Map<String, String> 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 extends RecognizerConvert> T convertRecognizerResult(
|
||||
RecognizerResult recognizerResult,
|
||||
Class<T> 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<RecognizerResult> recognizeInternal(
|
||||
TurnContext turnContext,
|
||||
LuisRecognizerOptions options,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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<RecognizerResult> recognizeInternal(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
LuisRecognizerOptions options,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics) {
|
||||
LuisRecognizerOptions predictionOptionsToRun = options == null ? luisRecognizerOptions : options;
|
||||
return predictionOptionsToRun.recognizeInternal(
|
||||
dialogContext,
|
||||
activity)
|
||||
.thenApply(recognizerResult -> {
|
||||
onRecognizerResult(
|
||||
recognizerResult,
|
||||
dialogContext.getContext(),
|
||||
telemetryProperties,
|
||||
telemetryMetrics);
|
||||
return recognizerResult;
|
||||
});
|
||||
}
|
||||
|
||||
private Map<String, IntentScore> sortIntents(RecognizerResult recognizerResult) {
|
||||
Map<String, IntentScore> 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;
|
||||
}
|
||||
}
|
|
@ -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<RecognizerResult> 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<RecognizerResult> recognizeInternal(
|
||||
DialogContext context,
|
||||
Activity activity);
|
||||
}
|
|
@ -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<String> dateSubtypes = new HashSet<>(
|
||||
Arrays.asList(
|
||||
"date",
|
||||
"daterange",
|
||||
"datetime",
|
||||
"datetimerange",
|
||||
"duration",
|
||||
"set",
|
||||
"time",
|
||||
"timerange"
|
||||
));
|
||||
|
||||
private final HashSet<String> 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<DynamicList> dynamicLists = null;
|
||||
|
||||
/**
|
||||
* External entities recognized in query.
|
||||
*/
|
||||
private List<ExternalEntity> 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<DynamicList> 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<DynamicList> dynamicLists) {
|
||||
this.dynamicLists = dynamicLists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets External entities to be recognized in query.
|
||||
* @return External entities to be recognized in query.
|
||||
*/
|
||||
public List<ExternalEntity> getExternalEntities() {
|
||||
return externalEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets External entities to be recognized in query.
|
||||
* @param externalEntities External entities to be recognized in query.
|
||||
*/
|
||||
public void setExternalEntities(List<ExternalEntity> 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<RecognizerResult> recognizeInternal(
|
||||
DialogContext dialogContext,
|
||||
Activity activity
|
||||
) {
|
||||
if (externalEntityRecognizer == null) {
|
||||
return recognizeInternal(
|
||||
dialogContext.getContext(),
|
||||
activity.getText());
|
||||
}
|
||||
|
||||
// call external entity recognizer
|
||||
List<ExternalEntity> originalExternalEntities = externalEntities;
|
||||
return externalEntityRecognizer
|
||||
.recognize(dialogContext, activity)
|
||||
.thenCompose(
|
||||
matches -> {
|
||||
if (matches.getEntities() == null
|
||||
|| matches.getEntities().toString().equals("{}")) {
|
||||
return recognizeInternal(
|
||||
dialogContext.getContext(),
|
||||
activity.getText());
|
||||
}
|
||||
|
||||
List<ExternalEntity> recognizerExternalEntities = new ArrayList<>();
|
||||
JsonNode entities = matches.getEntities();
|
||||
JsonNode instance = entities.get("$instance");
|
||||
|
||||
if (instance == null) {
|
||||
return recognizeInternal(
|
||||
dialogContext.getContext(),
|
||||
activity.getText());
|
||||
}
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> instanceEntitiesIterator = instance.fields();
|
||||
|
||||
while (instanceEntitiesIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> 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<RecognizerResult> 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<RecognizerResult> 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<RecognizerResult> 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<String, IntentScore> getIntents(JsonNode prediction) {
|
||||
Map<String, IntentScore> intents = new LinkedHashMap<>();
|
||||
|
||||
JsonNode intentsObject = prediction.get("intents");
|
||||
if (intentsObject == null) {
|
||||
return intents;
|
||||
}
|
||||
|
||||
for (Iterator<Map.Entry<String, JsonNode>> it = intentsObject.fields(); it.hasNext();) {
|
||||
Map.Entry<String, JsonNode> 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<String> 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<Map.Entry<String, JsonNode>> nodes = obj.fields();
|
||||
while (nodes.hasNext()) {
|
||||
Map.Entry<String, JsonNode> property = (Map.Entry<String, JsonNode>) 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<Map.Entry<String, JsonNode>> nodes = elt.fields();
|
||||
while (nodes.hasNext()) {
|
||||
Map.Entry<String, JsonNode> props = (Map.Entry<String, JsonNode>) 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<String, JsonNode> tokenProp = (Map.Entry<String, JsonNode>) 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<ResourceResponse> 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<ResourceResponse> exceptionResult = new CompletableFuture<>();
|
||||
exceptionResult.completeExceptionally(e);
|
||||
return exceptionResult;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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<RecognizerResult> recognize(
|
||||
TurnContext turnContext,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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 <T> 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 <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
TurnContext turnContext,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics,
|
||||
Class<T> c);
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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"));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<String, JsonNode> 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<ResourceResponse[]> sendActivities(
|
||||
TurnContext context,
|
||||
List<Activity> activities
|
||||
) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ResourceResponse> updateActivity(
|
||||
TurnContext context,
|
||||
Activity activity
|
||||
) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> 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<List<DynamicList>>() {});
|
||||
ObjectReader readerExternalentities = mapper.readerFor(new TypeReference<List<ExternalEntity>>() {});
|
||||
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());
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, IntentScore>(){{
|
||||
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<String, IntentScore>(){{
|
||||
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<String, IntentScore>(){{
|
||||
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<String, String> expectedProperties = new HashMap<String, String> (){{
|
||||
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<String, String> expectedProperties = new HashMap<String, String> (){{
|
||||
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<String, String> additionalProperties = new HashMap<String, String>(){{
|
||||
put("test", "testvalue");
|
||||
put("foo", "foovalue");
|
||||
}};
|
||||
Map<String, Double> telemetryMetrics = new HashMap<String, Double>(){{
|
||||
put("test", 3.1416);
|
||||
put("foo", 2.11);
|
||||
}};
|
||||
try {
|
||||
recognizer.recognize(turnContext, additionalProperties, telemetryMetrics).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Map<String, String> expectedProperties = new HashMap<String, String> (){{
|
||||
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<String, String> additionalProperties = new HashMap<String, String>(){{
|
||||
put("intentScore", "1.15");
|
||||
put("foo", "foovalue");
|
||||
}};
|
||||
Map<String, Double> telemetryMetrics = new HashMap<String, Double>(){{
|
||||
put("test", 3.1416);
|
||||
put("foo", 2.11);
|
||||
}};
|
||||
try {
|
||||
recognizer.recognize(turnContext, additionalProperties, telemetryMetrics).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Map<String, String> expectedProperties = new HashMap<String, String> (){{
|
||||
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));
|
||||
}
|
||||
}
|
1971
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite1.json
поставляемый
Normal file
1971
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite1.json
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
435
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite2.json
поставляемый
Normal file
435
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite2.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
461
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite3.json
поставляемый
Normal file
461
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Composite3.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
2541
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Contoso App.json
поставляемый
Normal file
2541
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Contoso App.json
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
75
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DateTimeReference.json
поставляемый
Normal file
75
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DateTimeReference.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
221
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DynamicListsAndList.json
поставляемый
Normal file
221
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/DynamicListsAndList.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
167
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndBuiltin.json
поставляемый
Normal file
167
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndBuiltin.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
196
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndComposite.json
поставляемый
Normal file
196
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndComposite.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
177
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndList.json
поставляемый
Normal file
177
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndList.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
166
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndRegex.json
поставляемый
Normal file
166
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndRegex.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
232
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimple.json
поставляемый
Normal file
232
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimple.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
239
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimpleOverride.json
поставляемый
Normal file
239
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalEntitiesAndSimpleOverride.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
201
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalRecognizer.json
поставляемый
Normal file
201
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/ExternalRecognizer.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
436
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/GeoPeopleOrdinal.json
поставляемый
Normal file
436
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/GeoPeopleOrdinal.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
143
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Minimal.json
поставляемый
Normal file
143
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Minimal.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
672
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/MinimalWithGeo.json
поставляемый
Normal file
672
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/MinimalWithGeo.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
41
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/NoEntitiesInstanceTrue.json
поставляемый
Normal file
41
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/NoEntitiesInstanceTrue.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
363
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Patterns.json
поставляемый
Normal file
363
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Patterns.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
351
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Prebuilt.json
поставляемый
Normal file
351
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Prebuilt.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
15
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TestRecognizerResultConvert.java
поставляемый
Normal file
15
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TestRecognizerResultConvert.java
поставляемый
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
247
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TraceActivity.json
поставляемый
Normal file
247
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TraceActivity.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
1971
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Typed.json
поставляемый
Normal file
1971
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/Typed.json
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
351
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TypedPrebuilt.json
поставляемый
Normal file
351
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/TypedPrebuilt.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
19
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/V1DatetimeResolution.json
поставляемый
Normal file
19
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/V1DatetimeResolution.json
поставляемый
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
2252
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/roles.json
поставляемый
Normal file
2252
libraries/bot-ai-luis-v3/src/test/java/com/microsoft/bot/ai/luis/testdata/roles.json
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -33,6 +33,18 @@ public class RecognizerResult implements RecognizerConvert {
|
|||
*/
|
||||
private HashMap<String, JsonNode> 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<String, IntentScore> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>Recognizers operate in a DialogContext environment to recognize user input into Intents
|
||||
* and Entities.</p>
|
||||
*
|
||||
* <p>
|
||||
* 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)
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
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<RecognizerResult> 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<RecognizerResult> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> 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 <T> The RecognizerConvert.
|
||||
* @return Analysis of utterance.
|
||||
*/
|
||||
public <T extends RecognizerConvert> CompletableFuture<T> recognize(
|
||||
DialogContext dialogContext,
|
||||
Activity activity,
|
||||
Map<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics,
|
||||
Class<T> 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<String, RecognizerResult> recognizerResults) {
|
||||
String text = null;
|
||||
List<JsonNode> candidates = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, RecognizerResult> 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<String, IntentScore> 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<String, String> fillRecognizerResultTelemetryProperties(
|
||||
RecognizerResult recognizerResult,
|
||||
Map<String, String> telemetryProperties,
|
||||
DialogContext dialogContext
|
||||
) {
|
||||
Map<String, String> 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<String, String> telemetryProperties,
|
||||
Map<String, Double> telemetryMetrics
|
||||
) {
|
||||
if (telemetryClient instanceof NullBotTelemetryClient) {
|
||||
BotTelemetryClient turnStateTelemetryClient = dialogContext.getContext()
|
||||
.getTurnState().get(BotTelemetryClient.class);
|
||||
telemetryClient = turnStateTelemetryClient != null ? turnStateTelemetryClient : telemetryClient;
|
||||
}
|
||||
|
||||
telemetryClient.trackEvent(eventName, telemetryProperties, telemetryMetrics);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||
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 final class Serialization {
|
|||
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 final class Serialization {
|
|||
public static JsonNode asNode(byte b) {
|
||||
return objectMapper.getNodeFactory().numberNode(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ObjectNode.
|
||||
* @return ObjectNode.
|
||||
*/
|
||||
public static ObjectNode createObjectNode() {
|
||||
return objectMapper.createObjectNode();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче