* 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:
Emilio Munoz 2021-02-11 12:35:46 -08:00 коммит произвёл GitHub
Родитель 497c35ee55
Коммит c057023b61
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
43 изменённых файлов: 17327 добавлений и 4 удалений

Просмотреть файл

@ -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));
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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();
}
}

Просмотреть файл

@ -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"
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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"
}
}
}

Просмотреть файл

@ -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"
}
}
]
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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();
}
}