java add utterances (#18)
This commit is contained in:
Родитель
469685b15e
Коммит
936c5a2956
|
@ -0,0 +1,347 @@
|
|||
// Add Utterances to LUIS Application - AddUtterances.java
|
||||
// Language Understanding Intelligent Service
|
||||
// Microsoft Cognitive Services, a part of Microsoft Azure
|
||||
//
|
||||
// Requires JDK 1.7 or later
|
||||
//
|
||||
// Package required: Google's GSON JSON library
|
||||
// Download latest JAR from GitHub: https://github.com/google/gson
|
||||
// and place it in the same directory as AddUtterances.java
|
||||
//
|
||||
// Paste your LUIS application ID, version, and subscription key in the
|
||||
// variables LUIS_APP_ID, LUIS_APP_VERSION, and LUIS_PROGRAMMATIC_KEY below.
|
||||
//
|
||||
// To compile from command line:
|
||||
//
|
||||
// javac -classpath gson-2.8.2.jar AddUtterances.java
|
||||
// java -classpath .;gson-2.8.2.jar AddUtterances
|
||||
// (substitute the correct name of the GSON JAR file)
|
||||
//
|
||||
// The utterances in the file ./utterances.json are added to your LUIS app.
|
||||
// The JSON response from the action is in the file utterances.results.json.
|
||||
//
|
||||
// You may add the following flags to the end of the run command:
|
||||
// -train Adds the utterances, starts training, and gets the training status
|
||||
// -status Gets the current training status (training may take a while)
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import com.google.gson.*;
|
||||
|
||||
//
|
||||
// AddUtterances container class. Holds LuisClient, LuisResponse, StatusException
|
||||
//
|
||||
public class AddUtterances {
|
||||
|
||||
// Enter information about your LUIS application and key below
|
||||
static final String LUIS_APP_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
static final String LUIS_APP_VERSION = "0.1";
|
||||
static final String LUIS_PROGRAMMATIC_KEY = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
|
||||
|
||||
// Update the host if your LUIS subscription is not in the West US region
|
||||
static final String LUIS_BASE = "https://westus.api.cognitive.microsoft.com";
|
||||
|
||||
// File names for utterance and result files
|
||||
static final String UTTERANCE_FILE = "./utterances.json";
|
||||
static final String RESULTS_FILE = "./utterances.results.json";
|
||||
|
||||
static final String UTF8 = "UTF-8";
|
||||
|
||||
//
|
||||
// LUIS Client class
|
||||
// Contains the functionality for adding utterances to a LUIS application
|
||||
//
|
||||
static class LuisClient{
|
||||
|
||||
private final String PATH = "/luis/api/v2.0/apps/{app_id}/versions/{app_version}";
|
||||
|
||||
// endpoint method names
|
||||
private final String TRAIN = "/train";
|
||||
private final String EXAMPLES = "/examples";
|
||||
private final String APP_INFO = "/";
|
||||
|
||||
// HTTP verbs
|
||||
private final String GET = "GET";
|
||||
private final String POST = "POST";
|
||||
|
||||
// Null string value for use in resolving method calls
|
||||
private final String NO_DATA = null;
|
||||
|
||||
// Member variables
|
||||
private String key;
|
||||
private String host;
|
||||
private String path;
|
||||
|
||||
LuisClient(String host, String app_id, String app_version, String key) throws Exception {
|
||||
this.path = PATH.replace("{app_id}", app_id).replace("{app_version}", app_version);
|
||||
this.host = host;
|
||||
this.key = key;
|
||||
|
||||
// Test configuration by getting the application info
|
||||
this.get(APP_INFO).raiseForStatus();
|
||||
}
|
||||
|
||||
LuisResponse call(String endpoint, String method, byte[] data) throws Exception {
|
||||
|
||||
// initialize HTTP connection
|
||||
URL url = new URL(this.host + this.path + endpoint);
|
||||
System.out.println(url + "\n\r");
|
||||
|
||||
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
|
||||
conn.setRequestMethod(method);
|
||||
conn.setRequestProperty("Ocp-Apim-Subscription-Key", key);
|
||||
|
||||
// handle POST request
|
||||
if (method.equals(POST) && data != null) {
|
||||
System.out.println(new String(data, UTF8));
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("Content-Length", Integer.toString(data.length));
|
||||
OutputStream ostream = conn.getOutputStream();
|
||||
ostream.write(data, 0, data.length);
|
||||
ostream.close();
|
||||
}
|
||||
|
||||
// Get response from API call. If response is an HTTP error, the JSON
|
||||
// response is on the error string. Otherwise, it's on the input string.
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = conn.getInputStream();
|
||||
} catch (IOException ex) {
|
||||
stream = conn.getErrorStream();
|
||||
}
|
||||
String body = new Scanner(stream, UTF8).useDelimiter("\\A").next();
|
||||
|
||||
return new LuisResponse(body, conn.getResponseCode(), conn.getResponseMessage());
|
||||
|
||||
}
|
||||
|
||||
// Overload of call() with String data paramater
|
||||
LuisResponse call(String endpoint, String method, String data) throws Exception {
|
||||
byte[] bytes = null;
|
||||
if (data != null)
|
||||
bytes = data.getBytes(UTF8);
|
||||
return call(endpoint, method, bytes);
|
||||
}
|
||||
|
||||
// Overload of call() with InputStream data paramater
|
||||
LuisResponse call(String endpoint, String method, InputStream stream) throws Exception {
|
||||
String data = new Scanner(stream, UTF8).useDelimiter("\\A").next();
|
||||
return call(endpoint, method, data);
|
||||
}
|
||||
|
||||
// Shortcut for GET requests
|
||||
LuisResponse get(String endpoint) throws Exception {
|
||||
return call(endpoint, GET, NO_DATA);
|
||||
}
|
||||
|
||||
// Shortcut for POST requests -- byte[] data
|
||||
LuisResponse post(String endpoint, byte[] data) throws Exception {
|
||||
return call(endpoint, POST, data);
|
||||
}
|
||||
|
||||
// Shortcut for POST requests -- String data
|
||||
LuisResponse post(String endpoint, String data) throws Exception {
|
||||
return call(endpoint, POST, data);
|
||||
}
|
||||
|
||||
// Shortcut for POST requests -- InputStream data
|
||||
LuisResponse post(String endpoint, InputStream data) throws Exception {
|
||||
return call(endpoint, POST, data);
|
||||
}
|
||||
|
||||
// Shortcut for POST requests -- no data
|
||||
LuisResponse post(String endpoint) throws Exception {
|
||||
return call(endpoint, POST, NO_DATA);
|
||||
}
|
||||
|
||||
// Call to add utterances
|
||||
public LuisResponse addUtterances(String filename) throws Exception {
|
||||
try (FileInputStream stream = new FileInputStream(filename)) {
|
||||
return post(EXAMPLES, stream);
|
||||
}
|
||||
}
|
||||
|
||||
public LuisResponse train() throws Exception {
|
||||
return post(TRAIN);
|
||||
}
|
||||
|
||||
public LuisResponse status() throws Exception {
|
||||
return get(TRAIN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// LUIS Response class
|
||||
// Represents a response from the LUIS client. All methods return
|
||||
// the instance so method calls can be chained.
|
||||
//
|
||||
static class LuisResponse {
|
||||
|
||||
private String body;
|
||||
private int status;
|
||||
private String reason;
|
||||
private JsonElement data;
|
||||
|
||||
LuisResponse(String body, int status, String reason) {
|
||||
JsonParser parser = new JsonParser();
|
||||
try {
|
||||
this.data = parser.parse(body);
|
||||
}
|
||||
catch (JsonSyntaxException ex) {
|
||||
this.data = parser.parse("{ \"message\": \"Invalid JSON response\" }");
|
||||
}
|
||||
this.body = new GsonBuilder().setPrettyPrinting().create().toJson(data);
|
||||
this.status = status;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
LuisResponse write(String filename) throws Exception {
|
||||
File file = new File(filename);
|
||||
if (!file.exists()) file.createNewFile();
|
||||
try (FileOutputStream stream = new FileOutputStream(file)) {
|
||||
stream.write(this.body.getBytes(UTF8));
|
||||
stream.flush();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
LuisResponse print() {
|
||||
System.out.println(this.body);
|
||||
return this;
|
||||
}
|
||||
|
||||
LuisResponse raiseForStatus() throws StatusException {
|
||||
if (this.status < 200 || this.status > 299) {
|
||||
throw new StatusException(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LUIS Status Exception class
|
||||
// Represents an exception raised by the LUIS client for HTTP status errors
|
||||
// Includes details extracted from the JSON response and the HTTP status
|
||||
//
|
||||
static class StatusException extends Exception {
|
||||
|
||||
private String details = "";
|
||||
private int status;
|
||||
|
||||
StatusException(LuisResponse response) {
|
||||
super(String.format("%d %s", response.status, response.reason));
|
||||
JsonObject jsonInfo = (JsonObject)response.data;
|
||||
if (jsonInfo.has("error"))
|
||||
jsonInfo = (JsonObject)jsonInfo.get("error");
|
||||
if (jsonInfo.has("message"))
|
||||
this.details = jsonInfo.get("message").getAsString();
|
||||
this.status = response.status;
|
||||
}
|
||||
|
||||
String getDetails() {
|
||||
return this.details;
|
||||
}
|
||||
|
||||
int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void printInvalidMsg(StatusException ex, String what, String variable) {
|
||||
String message = "Invalid %s. Set the variable %s to a valid LUIS %s";
|
||||
System.out.println(String.format(message, what, variable, what));
|
||||
System.out.println("in the Java source file " + ex.getStackTrace()[0].getFileName());
|
||||
}
|
||||
|
||||
static void printExceptionMsg(Exception ex) {
|
||||
System.out.println(String.format("%s: %s",
|
||||
ex.getClass().getSimpleName(), ex.getMessage()));
|
||||
|
||||
StackTraceElement caller = ex.getStackTrace()[1];
|
||||
System.out.println(String.format(" in %s (line %d?)",
|
||||
caller.getFileName(), caller.getLineNumber()));
|
||||
if (ex instanceof StatusException)
|
||||
System.out.println(((StatusException)ex).getDetails());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// Command-line entry point
|
||||
//
|
||||
public static void main(String[] args) {
|
||||
|
||||
// uncomment a line below to simulate command line options
|
||||
// args = new String[]{args[0], "-train"};
|
||||
// args = new String[]{args[0], "-status"};
|
||||
|
||||
LuisClient luis = null;
|
||||
|
||||
try {
|
||||
luis = new LuisClient(LUIS_BASE, LUIS_APP_ID,
|
||||
LUIS_APP_VERSION,LUIS_PROGRAMMATIC_KEY);
|
||||
} catch (StatusException ex) {
|
||||
int status = ex.getStatus();
|
||||
if (status == 401) {
|
||||
printInvalidMsg(ex, "app ID", "LUIS_APP_ID");
|
||||
}
|
||||
else if (status == 400) {
|
||||
printInvalidMsg(ex, "app ID", "LUIS_APP_ID");
|
||||
} else {
|
||||
printExceptionMsg(ex);
|
||||
}
|
||||
System.exit(0);
|
||||
} catch (Exception ex) {
|
||||
printExceptionMsg(ex);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// We shouldn't get here
|
||||
if (luis == null) {
|
||||
System.out.println("Unable to initialize LUIS client class.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (args.length > 1) { // handle command line flags
|
||||
String option = args[1].toLowerCase();
|
||||
if (option.startsWith("-")) // strip leading hyphens
|
||||
option = option.substring(option.lastIndexOf('-') + 1);
|
||||
if (option.equals("train")) {
|
||||
System.out.println("Adding utterance(s).");
|
||||
luis.addUtterances(UTTERANCE_FILE)
|
||||
.write(RESULTS_FILE)
|
||||
.raiseForStatus();
|
||||
System.out.println("Added utterance(s). Requesting training.");
|
||||
luis.train()
|
||||
.write(RESULTS_FILE)
|
||||
.raiseForStatus();
|
||||
System.out.println("Requested training. Requesting training status.");
|
||||
luis.status()
|
||||
.write(RESULTS_FILE)
|
||||
.raiseForStatus();
|
||||
} else if (option.equals("status")) {
|
||||
System.out.println("Requesting training status.");
|
||||
luis.status()
|
||||
.write(RESULTS_FILE)
|
||||
.raiseForStatus();
|
||||
}
|
||||
} else {
|
||||
System.out.println("Adding utterance(s).");
|
||||
luis.addUtterances(UTTERANCE_FILE)
|
||||
.write(RESULTS_FILE)
|
||||
.raiseForStatus();
|
||||
}
|
||||
|
||||
System.out.println("Success! Results in " + RESULTS_FILE);
|
||||
|
||||
} catch (Exception ex) {
|
||||
printExceptionMsg(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,297 @@
|
|||
{
|
||||
"luis_schema_version": "2.1.0",
|
||||
"versionId": "0.1",
|
||||
"name": "LUIS travel app",
|
||||
"desc": "",
|
||||
"culture": "en-us",
|
||||
"intents": [
|
||||
{
|
||||
"name": "BookFlight"
|
||||
},
|
||||
{
|
||||
"name": "None"
|
||||
},
|
||||
{
|
||||
"name": "OrderFood"
|
||||
},
|
||||
{
|
||||
"name": "Weather.GetForecast",
|
||||
"inherits": {
|
||||
"domain_name": "Weather",
|
||||
"model_name": "GetForecast"
|
||||
}
|
||||
}
|
||||
],
|
||||
"entities": [
|
||||
{
|
||||
"name": "Airline"
|
||||
},
|
||||
{
|
||||
"name": "DrinkSize"
|
||||
},
|
||||
{
|
||||
"name": "Location",
|
||||
"children": [
|
||||
"LocationTo",
|
||||
"LocationFrom"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PassengerCategory",
|
||||
"children": [
|
||||
"child",
|
||||
"infant",
|
||||
"adult"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TravelClass",
|
||||
"children": [
|
||||
"first",
|
||||
"economy",
|
||||
"business"
|
||||
]
|
||||
}
|
||||
],
|
||||
"composites": [
|
||||
{
|
||||
"name": "TicketsOrder",
|
||||
"children": [
|
||||
"PassengerCategory",
|
||||
"number",
|
||||
"TravelClass"
|
||||
]
|
||||
}
|
||||
],
|
||||
"closedLists": [
|
||||
{
|
||||
"name": "Coastal Cities",
|
||||
"subLists": [
|
||||
{
|
||||
"canonicalForm": "Barcelona",
|
||||
"list": [
|
||||
"capital city of catalonia",
|
||||
"bcn",
|
||||
"barna",
|
||||
"second spanish city"
|
||||
]
|
||||
},
|
||||
{
|
||||
"canonicalForm": "madrid",
|
||||
"list": [
|
||||
"mad"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"bing_entities": [
|
||||
"datetimeV2",
|
||||
"number"
|
||||
],
|
||||
"actions": [],
|
||||
"model_features": [],
|
||||
"regex_features": [],
|
||||
"utterances": [
|
||||
{
|
||||
"text": "drive me home",
|
||||
"intent": "None",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "go to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 6,
|
||||
"endPos": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "will it snow today",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "will it rain this weekend",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "book me a flight to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 20,
|
||||
"endPos": 24
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "i want to order lunch",
|
||||
"intent": "OrderFood",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "fly to cairo",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 7,
|
||||
"endPos": 11
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "flight to seattle",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 10,
|
||||
"endPos": 16
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "book me 2 adult business tickets to paris tomorrow on air france",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 36,
|
||||
"endPos": 40
|
||||
},
|
||||
{
|
||||
"entity": "PassengerCategory",
|
||||
"startPos": 10,
|
||||
"endPos": 14
|
||||
},
|
||||
{
|
||||
"entity": "TicketsOrder",
|
||||
"startPos": 8,
|
||||
"endPos": 23
|
||||
},
|
||||
{
|
||||
"entity": "Airline",
|
||||
"startPos": 54,
|
||||
"endPos": 63
|
||||
},
|
||||
{
|
||||
"entity": "TravelClass",
|
||||
"startPos": 16,
|
||||
"endPos": 23
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "ticket to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 10,
|
||||
"endPos": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "what is the weather in redmond ?",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "soliciting today's weather",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "forecast in celcius",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "will it be raining in ranchi",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "provide me by toronto weather please",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "\"i need to know the temperature at bangor, me\"",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "get the forcast for me",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "find out tomorrow's weather",
|
||||
"intent": "Weather.GetForecast",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "book a flight from seattle to hong kong",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 30,
|
||||
"endPos": 38
|
||||
},
|
||||
{
|
||||
"entity": "Location::LocationFrom",
|
||||
"startPos": 19,
|
||||
"endPos": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "buy a plane ticket to bangor me",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 22,
|
||||
"endPos": 30
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "reservation for new york city",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 25,
|
||||
"endPos": 28
|
||||
},
|
||||
{
|
||||
"entity": "Location",
|
||||
"startPos": 16,
|
||||
"endPos": 23
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "ticket to portland",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "Location::LocationTo",
|
||||
"startPos": 10,
|
||||
"endPos": 17
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"text": "go to Seattle",
|
||||
"intentName": "BookFlight",
|
||||
"entityLabels": [
|
||||
{
|
||||
"entityName": "Location::LocationTo",
|
||||
"startCharIndex": 6,
|
||||
"endCharIndex": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
,
|
||||
{
|
||||
"text": "book a flight",
|
||||
"intentName": "BookFlight",
|
||||
"entityLabels": []
|
||||
}
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"text": "go to Seattle",
|
||||
"intentName": "BookFlight",
|
||||
"entityLabels": [
|
||||
{
|
||||
"entityName": "Location::LocationTo",
|
||||
"startCharIndex": 6,
|
||||
"endCharIndex": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
,
|
||||
{
|
||||
"text": "book a flight",
|
||||
"intentName": "BookFlight",
|
||||
"entityLabels": []
|
||||
}
|
||||
]
|
|
@ -0,0 +1,16 @@
|
|||
[
|
||||
{
|
||||
"value": {
|
||||
"UtteranceText": "go to seattle",
|
||||
"ExampleId": -5123383
|
||||
},
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"UtteranceText": "book a flight",
|
||||
"ExampleId": -169157
|
||||
},
|
||||
"hasError": false
|
||||
}
|
||||
]
|
Загрузка…
Ссылка в новой задаче