UnityからLuisにリクエストを送る | Unity, 会話システム

コグニティブサービスの一種であるLUISを使って、Unityからリクエストを送るプログラムを作成しました。
作成したキャラクターと会話するときに使えるかと思ってメモ。

#実行環境
Unity
LUIS(Language Understanding Intelligent Service)
 - Microsoftが開発した認識システム
 - 発言した内容のインテントやエンティティを返すことができる

##各種インストール
1. 以下のツールをPCにインストール
 - [Unity](https://store.unity.com/ja)

2. 次に[LUIS](https://www.luis.ai)のサインアップを行います

##認識ワードの設定（LUIS）
LUISを使って「おはよう」と入力すると、以下のようにjsonが返ってくるものを作成します。

```
{
  "query": "おはよう",
  "topScoringIntent": {
    "intent": "挨拶をしたい",
    "score": 0.9781246
  },
  "intents": [
    {
      "intent": "挨拶をしたい",
      "score": 0.9781246
    },
    {
      "intent": "None",
      "score": 0.01577978
    }
  ],
  "entities": []
}
```

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/104887/eaa3bc26-5f5a-d364-113c-46adcac807e2.png)


#プログラム作成
今回はInputFieldを使って文字列をLUISに送りました。

InputFieldにLuis.csをドラッグ、
InputField->On End EditのプルダウンからLuis->InputLoggerを選択

※参考： [PG日誌](http://takachan.hatenablog.com/entry/2017/01/18/120000) [TECK Pjin](http://tech.pjin.jp/blog/2016/09/27/unity_skill_4/)

```cs:Luis.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Networking;

public class Luis : MonoBehaviour {
    InputField inputField;
    string inputValue;
    public string mystr = "Failed get Request";
    string requestMessage = "null";

    // Use this for initialization
    void Start () {
        inputField = GetComponent<InputField>();
    }

    public void InputLogger()
    {sakus
        inputValue = inputField.text;
        Debug.Log("Input is : " + inputValue);


        StartCoroutine(GetTexture());
    }

    public IEnumerator GetTexture()
    {
        UnityWebRequest www = UnityWebRequest.Get("https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/~~&q=" + WWW.EscapeURL(inputValue));

        AsyncOperation checkAsync = www.Send();
        while (!checkAsync.isDone) ;
        //Debug.Log("Request Async is " + checkAsync.isDone);

        if (www.isError)
        {
            mystr = www.error;  //unknown error
            Debug.Log(www.error);
        }
        else
        {
            var json = www.downloadHandler.text;
            var x = JsonUtility.FromJson<JsonFunc<Queries>>(json);
            Debug.Log("Luis.cs Get data : " + json);
            Debug.Log("Received Query: " + x.query);
            Debug.Log("Received Intent: " + x.topScoringIntent.intent);
            Debug.Log("Received Score: " + x.topScoringIntent.score);


            mystr = x.topScoringIntent.intent;
        }

        inputField.text = "";
        inputField.ActivateInputField();

        yield return null;
    }
}

```

```cs:JsonFunc
using System;
using UnityEngine;
using System.Collections;

//Jsonに関する処理を行うクラス
[Serializable]
public class JsonFunc<T>
{
    public string query;
    public T topScoringIntent;

    public JsonFunc(string query, T topScoringIntent)
    {
        this.query = query;
        this.topScoringIntent = topScoringIntent;
        //Debug.Log("FromJson:" + this.data);
    }
}

[Serializable]
public class Queries
{
    public string intent;
    public double score;

    public Queries(string intent, double score) //ここのintentとかはluisの要素と一緒にしないとダメかも
    {
        this.intent = intent;
        this.score = score;
    }
}
```

#実行結果
以下のようなログが出たらOK
![log.png](https://qiita-image-store.s3.amazonaws.com/0/104887/820b0a38-a4e9-2549-ef09-2d53f3714c35.png)

#プログラム詳細
気になったところだけメモ

##Webリクエスト
UnityWebRequest.Get引数の中にそのまま日本語文字列を入れてしまうと文字化けを起こし、期待したjsonコードが返ってきません。
そこでWWW.EscapeURLを使ってURLエンコードをする必要があります。

```
UnityWebRequest www = UnityWebRequest.Get("https://westus.api.cognitive.microsoft.com/luis~~q=" + WWW.EscapeURL(requestMessage));

AsyncOperation checkAsync = www.Send();
while (!checkAsync.isDone) ;
```

##デシリアライズ
作成したJsonFunc.csを使って、jsonから要素を取り出す作業を行います。
今回はLUISから返ってきたデータを処理するだけなので、シリアライズはしません。

```
var json = www.downloadHandler.text;
var x = JsonUtility.FromJson<JsonFunc<Queries>>(json);
Debug.Log("Luis.cs Get data : " + json);
Debug.Log("Received Query: " + x.query);
Debug.Log("Received Intent: " + x.topScoringIntent.intent);
Debug.Log("Received Score: " + x.topScoringIntent.score);
```