# 使用场景

请参考动态实体介绍文档

# 动态实体

# 动态实体定义

一个动态实体的定义可以包含多个资源Resource的定义,资源定义中包含了资源名称,以及从客户端上传数据抽取说法的字段名以及生效的维度。 生效的维度目前有用户级(uid)应用级(appid)自定义级,在客户端上传对应的资源数据时,维度信息需要和定义时保持一致。

# 动态上传资源数据

通过CMD_SYNC 上传同步资源数据,arg1表示同步的数据类型,动态实体对应SYNC_DATA_SCHEMA(常量对应值为3)。 data为同步JSON内容的utf-8二进制数据。 JSON内容示例如下:

{
	"param": {
		"id_name": "uid",   // 维度
		"id_value": "", // 维度具体值,当维度取uid或appid时,该值可取空,AIUI会自动补全
		"res_name": "XXX.user_applist"  // 资源名称
	},
	"data": "xxxxxx"// 与schema名称对应的数据内容base64编码
}

注意:同步数据前需确保设备已经连接到AIUI服务器,可通过接收到EVENT_CONNECTED_TO_SERVER事件来判断,当收到EVENT_SERVER_DISCONNECTED事件后,将不能进行同步个性化数据等操作。

**XXX为用户的命名空间

id_name与动态实体定义资源时指定的维度对应,如果定义时是用户级,那此处id_name就对应uidid_value是维度具体值,如id_nameuidid_value就需要是该资源针对生效的用户的具体UID,AIUI会使用 当前用户UID进行补全,appid同理。自定义维度因为是由开发者自定义,所以id_nameid_value都需要设置具体值。

通过指定id_nameid_value,上传的动态实体资源数据到服务端就有了唯一的从属,在生效使用时就可以指定此处的id_nameid_value的值就能生效使用当前上传的动态实体资源。

res_name对应的是平台自定义动态实体资源名,格式:“命名空间.资源名”。

data中是原始资源数据的base64编码内容。原始资源数据是包含多条json记录的文本,通过动态实体定义时的抽取字段名可以从每条 json记录中抽取出定义支持的说法。

如定义资源时数据抽取的主列名为appName,别名为alias,那就要确保每条json记录中都要包含如上的字段(可以包含冗余字段,如下面的extra字段), 示例如下:

{"appName": "微信""alias": "wechat", "extra": "xxx"}
{"appName": "新浪微博""alias": "微博", "extra": "yyy"}
{"appName": "Telegram""alias": "电报", "extra": "zzz"}
{"appName": "讯飞输入法""alias": "", "extra": "uuu"}

注:每条数据之间用换行符隔开。

data的实际内容是将如上数据进行base64编码后的结果。

同步上传的代码示例如下:

JSONObject syncSchemaJson = new JSONObject();

JSONObject paramJson = new JSONObject();

paramJson.put("id_name", "uid");
paramJson.put("res_name", "XXX.user_applist");

syncSchemaJson.put("param", paramJson);
syncSchemaJson.put("data", Base64.encodeToString(FileUtil.readAssetsFile(context, "file_path"),  Base64.DEFAULT | Base64.NO_WRAP));

// 传入的数据一定要为utf-8编码
byte[] syncData = syncSchemaJson.toString().getBytes("utf-8");

AIUIMessage syncAthenaMessage = new AIUIMessage(AIUIConstant.CMD_SYNC,AIUIConstant.SYNC_DATA_SCHEMA, 0, "", syncData);
mAIUIAgent.sendMessage(syncAthenaMessage);

CMD_SYNC完成后会有EVENT_CMD_RETURN事件回调,可以获取该操作对应的sid,便于后面查询使用:

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

若用户需要同时上传多条数据,但在上传结果回调里无法将上传数据与结果一一对应时,可在上传资源数据时加上sync_tag标签,数据上传后,在结果回调里也会将此标签带出。用户可通过此标签,将结果与上传数据对应。

上传使用示例如下:

String dataTag = "data_tag_1";
JsonObject params = new JsonObject();
params.put("tag", dataTag);

AIUIMessage syncAthenaMessage = new AIUIMessage(AIUIConstant.CMD_SYNC,AIUIConstant.SYNC_DATA_SCHEMA, 0, params.toString(), syncData);
mAIUIAgent.sendMessage(syncAthenaMessage);

结果回调示例如下:

private void processCmdReturnEvent(AIUIEvent event) {
	switch (event.arg1) {
		case AIUIConstant.CMD_SYNC: {
			int dtype = event.data.getInt("sync_dtype");
			String sync_tag = event.data.getString("tag");
		} break;
	}
}

注意

  1. 具体代码示例工程可参考AIUIChatDemo (opens new window)中AIUIRepository类的syncDynamicEntity方法实现。
  2. 动态实体上传后5min生效。

# 查询打包状态

通过CMD_SYNC上传同步动态实体的资源数据后,AIUI服务端会进行处理然后生效,处理的过程是异步的,可以通过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;
	}
}

注意

  1. 请上传资源数据后至少间隔10秒后再进行查询打包状态操作。
  2. 具体代码示例工程可参考AIUIChatDemo (opens new window)中AIUIRepository类的syncDynamicEntity方法实现。
  3. 动态实体上传后5min生效。

# 生效使用

通过CMD_SET_PARAMS设置pers_param即可使用已设置的动态实体(CMD_SET_PARAMS具体用法参见动态配置

生效应用级动态实体:

{
	"audioparams": {
		"pers_param":"{\"appid\":\"\"}"
	}
}

生效用户级动态实体:

{
	"audioparams": {
		"pers_param":"{\"uid\":\"\"}"
	}
}

生效自定义级动态实体:

{
	"audioparams": {
		"pers_param":"{\"custom_key\":\"custom_val\"}"
	}
}

如果需要在本机器上生效当前应用对应的所有应用级的动态实体,在pers_param加入\"appid\":\"\"(值留空, AIUI中会自动补全appid和uid的值),同理用户级动态实体生效需要加入\"uid\":\"\"

对于自定义维度需要用后台定义实体时的自定义维度名作为key,使用动态上传指定的自定义维度作为值。如 后台定义的自定义维度名为vendor,那在动态上传时就需要构造如下数据进行上传:

{
	"param": {
		"appid": "xxxxxx",// 雅典娜开放平台appid
		"id_name": "vendor",// 自定义维度名
		"id_value": "spec_vendor",  // 自定义维度value
		"res_name": "user_applist"  // 资源名称
	},
	"data": "xxxxxx"// 与schema名称对应的数据内容base64编码
}

那对应需要在交互时使用该自定义维度对应的动态实体就需要加入\"vendor\":\"spec_vendor\"

除了通过CMD_SET_PARAMS设置pers_param

注意: set audioParams这种方式只会对语音交互生效,文本语义参考下面数据写入带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(), "");
mAgent.sendMessage(setMsg);

也可以在音频写入时设置该参数:

//写入音频
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);

如需同时生效使用多种级别的动态实体,可直接在pers_param里添加对应的级别的参数即可,示例如下:

{
	"audioparams": {
		"pers_param":"{\"appid\":\"\", \"uid\":\"\"}"
	}
}

audioParams.put("pers_param", "{\"appid\":\"\", \"uid\":\"\"}");

注意

  1. 具体代码示例工程可参考AIUIChatDemo (opens new window)中AIUIRepository类的syncDynamicEntity方法实现。
  2. 动态实体上传后5min生效。

# 开放动态实体

开发者除了使用自定义的动态实体外,还可以使用平台提供的开放动态实体。在一些通用场景里,开发者可以省去定义开放实体的步骤,直接上传使用即可。平台提供两种开放动态实体,按如下格式上传资源,打包成功后即可生效使用。

# 联系人实体

联系人实体对应的资源名为IFLYTEK.telephone_contact,对应的关联技能为“电话”,为用户级动态实体,可定义数据格式如下所示:

{"name":"张三","alias":"三弟","phoneNumber":"18888888888","location":{}}
{"name":"李四","alias":"四妹","phoneNumber":"18666666666","location":{}}

name字段必不可少且不为空,alias为从字段,可设置别名,phoneNumber为电话号码,location为可选字段,可自定义其内容。

# 智能家居个性化实体

智能家居个性化动态实体也是用户级动态实体,其可上传的动态实体资源有6个,对应的关联技能为所有智能家居业务,资源定义如下所示:

  • IFLYTEK.smartH_deviceAlias     对应的字段为alias
  • IFLYTEK.smartH_deviceModi     对应的字段为modifier
  • IFLYTEK.smartH_deviceRoom     对应的字段为room
  • IFLYTEK.smartH_deviceZone     对应的字段为zone
  • IFLYTEK.smartH_deviceRegion    对应的字段为region
  • IFLYTEK.smartH_deviceScene    对应的字段为scene

上传动态实体资源时alias资源为必传资源,其他的为可选上传资源。具体以一个名为大白的空调设备来说明如何上传智能家居个性化实体。

① 上传alias资源。用户查询使用的时候返回的所有数据都是从这条资源里返回的,因此上传该资源时请尽量包含您想要的信息。示例JSON格式定义如下:

{"modifier": "海尔","color": "白色","location": {"room": "卧室","zone": "二楼","region": "兴园"},"type": "空调壁挂式","description": "卧室空调","model": "健康卫士系列","feature": "制冷|制热|除湿|除菌|静音|自动|送风|净化|背景灯|电辅","did": "1511505251","device": "airControl","alias": "大白"}

② 上传modifier资源,该设备对应的品牌信息,以下三个字段皆为必选。

{"modifier":"海尔","did":"1511505251","device":"airControl"}

③ 上传room资源,该设备对应的房间信息,以下三个字段皆为必选。

{"room" : "卧室","did":"1511505251","device":"airControl"}

④ 上传zone资源,该设备对应的空间信息,以下三个字段皆为必选。

{"zone" : "二楼""did":"1511505251","device":"airControl"}

⑤ 上传region资源,该设备对应的地理位置信息,以下三个字段皆为必选。

{"region":"兴园","did":"1511505251","device":"airControl"}

⑥ 上传scene资源,应用所具有的情景模式信息,以下两个字段皆为必选,且其device字段的值为固定的。

{"scene":"狂欢|安全","device":"group"}

注意事项:

① device字段的值与AIUI开放平台的智能家居技能是对应的,如空调技能对应的device值为airControl,豆浆机对应soymilk,空气净化器对应airCleaner等等。其他智能家居技能的具体取值可在开放技能勾选页面查看,如下图所示,取_smartHome前面的名字即可。

② 除scene实体外,其他每个实体在上传每一条智能家居动态实体资源时,都必须包含diddevice字段。

③ 上传资源数据时应构造json对象,再将其转成字符串,而不是直接使用字符串。

④ scene资源为应用所具备的所有情景模式,是一个单独的实体,并不单独针对某个设备,不跟某个设备进行关联,用户接收到该语义结果后客户端需根据返回的情景模式自行处理。

# 动态实体QA

Q:上传资源数据返回的状态与查询打包状态有什么区别?

**A:**上传资源数据时返回的状态代表数据是否上传成功至服务端,主要是用来反馈上传的数据格式是否正确;查询打包状态代表数据上传至后台后是否将这些资源数据处理成功,主要是用来反馈数据能否被正常生效使用。

Q:动态实体上传失败的原因一般有哪些?

**A:**①res_name未加上命名空间;②上传资源字段与后台不对应

Q:动态实体不能正常生效使用的原因一般有哪些?

**A:**①未设置pers_param参数;②上传资源数据时如果是在文本文件里读取的内容,请注意不要将文件的BOM头带入数据中或者直接将其转为无BOM头的文件;③aiui.cfg文件里未指定appid。