**給大家帶來一個AIUI動態實體使用的簡易教程**
**場景:小明想通過AIUI了解西游記里各位角色都是啥樣的,小明對AIUI說`我想聽孫悟空的故事`,AIUI馬上將孫悟空的大鬧天宮播放了出來。**
**請跟著我一步步將這個場景實現。**
**小明想說的話我們把它抽象為一個技能,一個技能可以有多種說法,這里我們列舉兩種說法,在AIUI開放平臺上創建出來。①我想聽xxx的故事,②介紹一下xxx。**
#### 1. 創建技能
登錄[AIUI開放平臺](http://aiui.xfyun.cn),選擇我的技能->創建新技能,填寫技能名稱與語料,但是語料該怎么寫呢?我們可以把我想聽xxx的故事中的xxx抽象出一個動態實體資源出來,用一個代號來命名它,這里我們命名為`{name}`,于是語料產生了,①我想聽{name}的故事,②介紹一下{name}。

**但是當創建完技能后,我們去哪兒找人物名的資源呢。這里我們就需要創建一個動態實體資源啦,來與這個技能關聯起來**
#### 2. 創建資源
選擇我的技能->我的實體->創建新實體->動態實體,即可創建想要的動態實體資源。如下圖所示創建了一個應用級的動態實體資源,里面用來定義西游記角色的名字。

**創建完資源后需要將技能語料中的語義槽與實體關聯起來。**
**技能我們創建好了,但是技能在哪兒使用呢,當然是在應用中啦~ 我們需要在自己的應用中添加上我們自定義的技能。**
#### 3. 創建AIUI應用并關聯技能
在[AIUI開放平臺](http://aiui.xfyun.cn)創建好應用后,再將第2步創建好的技能添加至應用中。

下載SDK,在本地創建相應工程,開始集成AIUI。具體步驟參考[AIUI Mobile Training](http://www.hmoore.net/aiui_client/aiui_mobile_userguide/405299)。已集成過AIUI的工程可忽略此步驟。
**AIUI基本的功能可以正常使用后,我們馬上就可以使用神奇的動態實體功能啦。首先需要將動態實體數據上傳到服務器中。**
#### 4. 上傳動態實體資源數據
在aiui_phone.cfg文件里添加上login字段,將你應用的appid填寫進去,如下圖所示:

將需要上傳的數據通過AIUIAgent上傳至AIUI服務器。這里以Android平臺為例,介紹下如何上傳動態實體資源數據。
~~~
//待上傳的數據
String data ="{\"name\": \"孫悟空\", \"alias\": \"齊天大圣\" }\n" +
"{\"name\": \"唐三藏\", \"alias\": \"唐僧\" }\n" +
"{\"name\": \"豬八戒\", \"alias\": \"天蓬元帥\" }";
//應用級參數json
JSONObject paramJson = new JSONObject();
paramJson.put("appid", 你自己的appid); //這里注意填寫上你應用的appid,String型
paramJson.put("id_name", "appid");
paramJson.put("id_value", "");
paramJson.put("res_name", "BLACKSHIP.CharacterName");
//數據json
JSONObject syncSchemaJson = new JSONObject();
syncSchemaJson.put("param", paramJson);
syncSchemaJson.put("data", Base64.encodeToString(data.getBytes(), Base64.DEFAULT | Base64.NO_WRAP));
//上傳資源數據
byte[] syncData = syncSchemaJson.toString().getBytes("utf-8");
AIUIMessage syncAthenaMessage = new AIUIMessage(AIUIConstant.CMD_SYNC,AIUIConstant.SYNC_DATA_SCHEMA, 0, "", syncData);
mAIUIAgent.sendMessage(syncAthenaMessage);
~~~
上面為上傳應用級動態實體示例,如需上傳用戶級動態實體,將參數json中`id_name`的值從`appid`改為`uid`即可。
如需上傳自定義級別動態實體,將參數json中`id_name`的值改為[AIUI開放平臺](http://aiui.xfyun.cn)對應資源的維度名,將`id_value`的值修改為自己想要的值即可。如下圖所示后臺定義的維度名為`area`。

**數據我們是上傳上去了,但是數據對不對呢?當然得有個反饋來告訴你,數據傳得成功與否,對錯與否。我們可以在上傳結果回調里看到。**
#### 5. 上傳結果回調
動態實體資源上傳后,會有`EVENT_CMD_RETURN`事件回調,通知開發者數據是否上傳成功。如成功可進行下一步,如不成功需要重新檢查上傳時是否存在參數錯誤、或數據格式不正確等,再重新上傳。代碼示例如下:
~~~
private void processCmdReturnEvent(AIUIEvent event) {
switch (event.arg1) {
case AIUIConstant.CMD_SYNC: {
int dtype = event.data.getInt("sync_dtype");
//arg2表示結果
if (0 == event.arg2) { // 同步成功
if (AIUIConstant.SYNC_DATA_SCHEMA == dtype) {
mSyncSid = event.data.getString("sid");
showTip("schema數據同步成功,sid=" + mSyncSid);
}
} else {
if (AIUIConstant.SYNC_DATA_SCHEMA == dtype) {
mSyncSid = event.data.getString("sid");
showTip("schema數據同步出錯:" + event.arg2 + ",sid=" + mSyncSid);
}
}
} break;
}
}
~~~
**如果數據上傳成功了,我們就可以進行下一步了,查詢我們上傳的數據服務器是否打包成功了。**
#### 6. 查詢打包狀態
數據成功上傳至后臺后,后臺會將數據進行打包處理,這個過程是異步的,需要通過`CMD_QUERY_SYNC_STATUS`查詢上傳的資源數據是否處理成功。只有當處理成功后,后續才可以正常使用。
arg1表示狀態查詢的類型,動態實體對應`SYNC_DATA_SCHEMA`(常量對應值為3),params為json,包含需要對應同步上傳操作的sid,示例如下:
~~~
JSONObject paramsJson = new JSONObject();
paramsJson.put("sid", mSyncSid);
AIUIMessage querySyncMsg = new AIUIMessage(AIUIConstant.CMD_QUERY_SYNC_STATUS,
AIUIConstant.SYNC_DATA_SCHEMA, 0,
paramsJson.toString(), null);
mAIUIAgent.sendMessage(querySyncMsg);
~~~
`CMD_QUERY_SYNC_STATUS`執行完成后會有`EVENT_CMD_RETURN`事件回調,表示查詢結果,解析示例如下:
~~~
private void processCmdReturnEvent(AIUIEvent event) {
switch (event.arg1) {
//schema數據打包結果查詢結果
case AIUIConstant.CMD_QUERY_SYNC_STATUS: {
int syncType = event.data.getInt("sync_dtype");
if (AIUIConstant.SYNC_DATA_QUERY == syncType) {
String result = event.data.getString("result");
if (0 == event.arg2) {
showTip("查詢結果:" + result);
} else {
showTip("schema數據狀態查詢出錯:" + event.arg2 +
", result:" + result);
}
}
} break;
}
}
~~~
**如果數據處理沒成功,我們可以稍微等幾秒再查詢一次,如果數據處理成功了,我們就可以正常來使用我們剛剛上傳上去的數據了,是不是很雞凍?(?>?<?)?**
#### 7. 生效使用
**① 通過`CMD_SET_PARAMS`設置`pers_param`即可使用已設置的動態實體**
生效應用級示例如下:
~~~
JSONObject params = new JSONObject();
JSONObject audioParams = new JSONObject();
audioParams.put("pers_param", "{\"appid\":\"\"}");
params.put("audioparams", audioParams);
AIUIMessage setMsg = new AIUIMessage(CMD_SET_PARAMS, 0 , 0, params.toString(), null);
mAgent.sendMessage(setMsg)
String params = "data_type=audio,sample_rate=16000";
AIUIMessage msg = new AIUIMessage(AIUIConstant.START_RECORD, 0, 0, params, null);
mAIUIAgent.sendMessage(msg);
~~~
**注意: set audioParams這種方式只會對語音交互生效,文本語義不生效,可采用第二種方式**
**② 直接帶入params參數中**
~~~
//寫入音頻
byte[] audio = xxx; //初始化
String params = "data_type=audio,sample_rate=16000,pers_param={\"appid\":\"\"}";
AIUIMessage msg = new AIUIMessage(AIUIConstant.CMD_WRITE, 0, 0, params, audio);
mAIUIAgent.sendMessage(msg);
~~~
~~~
//文本語義
String params = "data_type=text,pers_param={\"appid\":\"\"}";
AIUIMessage writeMsg = new AIUIMessage( AIUIConstant.CMD_WRITE, 0, 0, params, "介紹一下孫悟空".getBytes());
mAIUIAgent.sendMessage(writeMsg);
~~~
**發送了音頻或者文本以后,你會收到你的技能語料以及你想聽的是哪個人物的故事了。但是怎么去請求該人物的故事呢,這就要靠廣大的開發者根據該人物的名稱去請求你們自己的服務將故事下發下來了~~**