回调接口
PAI-Rec包含内置的回调接口。回调接口主要用来记录推荐请求时刻的实时特征日志,包括请求参数、用户和物品的实时特征,可以用于后续的数据分析、离线模型训练或在线学习。
背景
实时特征是推荐中很重要的一环,包括实时统计特征和实时序列特征,尤其是其中的用户实时序列特征。一般来说,增加实时特征能明显的提升推荐系统的效果。然而实时特征对准确性的要求很高,如通过离线卡时间窗口关联的方式(指通过离线日志反推在推荐时刻用户和物品的实时特征),由于很难估计系统各链路间的延时,很容易就出现特征不准确、特征穿越的问题,在召回和排序模型中加上这些不准确的特征得到适得其反的效果。
如何定义准确性?一个训练样本S_i(对应推荐请求R_i)中的实时特征,需要是推荐请求R_i时刻的user和item特征,因此最佳保证实时特征是在推荐请求打到推荐服务的时候,在算法计算推荐结果的同时,把recomid+user的实时特征+item的实时特征落入日志中(如datahub/kafka等),然后再同步到 MaxCompute(ODPS) 中。
然而往往因为AB实验的原因,一个推荐服务不是接受所有的实验流量的,没有办法给所有的实验流量来落实时特征,训练的时候又往往需要全量的训练样本进行训练,这些样本都需要有实时特征才能发挥实时特征的效果。因此,最佳近似实时的方式是通过callback接口,简单来说,A服务如果想落实时特征(f1,f2,f3...),B服务在下发之前,会异步调用A服务的callback接口,告诉A服务下发列表,让A服务把这些特征给落下来。该方案灵活性也较高,A服务想落的实时特征不会跟B服务想落的产生冲突,且实时性有保障,下发时刻和算法获取特征的时刻是近似同时的,不会出现特征穿越的问题。
接口定义
接口名称
/api/callback
请求参数
参数名称 | 参数类型 | 是否必须 | 参数说明 | 用例 |
scene_id | string | 是 | 首页推荐 | homepage |
uid | string | 是 | 用户注册ID | 85578510 |
request_id | string | 是 | 请求的唯一标识 | d9cb1c8d-4d3f-491b-9ea3-380481dabde3 |
features | json string | 否 | 用户特征 | {"age":25, "city":"beijing"} |
item_list | json list | 是 | 推荐的uid列表 | [{"item_id":"99886867"}, {"item_id":"99888623"}] |
request_info | json string | 否 | 请求信息 | {"recom_id":"12334234"} |
请求样例
curl 'http://host/api/callback' -d '{"uid":"84603208","request_id":"d9cb1c8d-4d3f-491b-9ea3-380481dabde3","scene_id":"homepage","features":{"age":25, "city":"beijing"}, "item_list":[{"item_id":"113939841"},{"item_id":"113764910"}],"request_info":{"recom_id":"1111111"}}'
返回数据
{
"code":200,
"msg":"success",
}
字段 | 类型 | 描述 | 示例 |
code | integer | 返回码标识 | 接口状态码,200成功 |
msg | string | 提示信息 | 成功为success |
回调配置
Callback 流程主要分两部分
加载 user/item 特征,
很多情况下如果使用 EasyRec 模型, item 特征是与模型绑定到一起的。 需要请求 easyrec 模型,拿到模型生成的 FG 特征
把上面的特征数据写入到消息队列(datahub) 中。
"CallBackConfs": {
"home_feed": {
"DataSource": {
"Name": "pairec_callback_dh",
"Type": "datahub"
},
"RankConf": {
"RankAlgoList": [
"ali_rnk_v2_woid_callback_public_v2"
],
"ContextFeatures": [
"none"
],
"Processor": "EasyRec"
}
}
}
home_feed 是场景名称,针对哪个场景落日志
DataSource
Type 消息队列类型,目前支持 datahub
pairec_callback_dh datahub 的数据源名称, 在 DatahubConfs 能找到
RankConf 配置的模型信息,和正常的引擎服务的模型配置一样,如果没有模型产生的特征信息,可以不配置
数据源配置
"DatahubConfs": {
"pairec_callback_dh": {
"Endpoint": "http://dh-cn-hangzhou-int-vpc.aliyuncs.com",
"AccessId": "${AccessId}",
"AccessKey": "${AccessKey}",
"ProjectName": "<ProjectName>",
"TopicName": "pairec_callback_log",
"Schemas": [
{
"Field": "request_id",
"Type": "string"
},
{
"Field": "module",
"Type": "string"
},
{
"Field": "scene",
"Type": "string"
},
{
"Field": "request_time",
"Type": "integer"
},
{
"Field": "user_features",
"Type": "string"
},
{
"Field": "item_features",
"Type": "string"
},
{
"Field": "request_info",
"Type": "string"
},
{
"Field": "user_id",
"Type": "string"
},
{
"Field": "item_id",
"Type": "string"
},
{
"Field": "raw_features",
"Type": "string"
},
{
"Field": "generate_features",
"Type": "string"
},
{
"Field": "context_features",
"Type": "string"
}
]
}
}
注:如果使用 PAI-Rec 控制台进行配置,为了保持安全性,${AccessId}与${AccessKey} 可以不用替换,引擎会自动替换。
在上面的配置中, topic name 可以不用手动创建, PAI-Rec 可以根据 topic name 及 schema 自动创建。
特征加载配置
特征加载配置 参考。这里不同一点就是场景名称 + _callback 作为特征加载的场景别名。
home_feed_callback 的场景名称是 home_feed + _callback 来的。
"FeatureConfs": {
"home_feed_callback": {
"AsynLoadFeature": true,
"FeatureLoadConfs": [
{
"FeatureDaoConf": {
"AdapterType": "hologres",
"HologresName": "pairec-holo",
"FeatureKey": "user:uid",
"UserFeatureKeyName": "client_str",
"HologresTableName": "dwd_ali_user_all_feature_v2_holo",
"UserSelectFields": "*",
"FeatureStore": "user"
},
"Features": [
{
"FeatureType": "new_feature",
"FeatureName": "day_h",
"Normalizer": "hour_in_day",
"FeatureStore": "user"
},
{
"FeatureType": "new_feature",
"FeatureName": "week_day",
"Normalizer": "weekday",
"FeatureStore": "user"
},
{
"FeatureType": "new_feature",
"FeatureName": "rand_int_v",
"Normalizer": "random",
"FeatureStore": "user"
}
]
},
{
"FeatureDaoConf": {
"AdapterType": "hologres",
"HologresName": "pairec-holo",
"FeatureKey": "user:uid",
"UserFeatureKeyName": "client_str",
"HologresTableName": "dwd_ali_user_table_v3_expo_static_feature_v2_holo",
"UserSelectFields": "*",
"FeatureStore": "user"
}
}
]
}
}
日志格式
callback 请求数据包含一个 uid + item 列表。 很多请求下, user 的特征比较大,为了省空间,我们会把 user 特征和 item 特征分开落下来。
user 特征日志,包含下面数据
request_id 请求ID, callback 请求里获得
scene 场景名称,callback 请求里获得
request_time 请求时间
user_features user 特征, json string
user_id 用户ID标识
request_info 额外的请求信息, callback 请求里获得
module 固定值 user , 表明是 user 特征
item 特征日志,包含下面数据
request_id 请求ID, callback 请求里获得
scene 场景名称,callback 请求里获得
request_time 请求时间
module 固定值 item , 表明是 item 特征
item_id item ID 标识
user_id 用户ID标识
raw_features easyrec 模型返回raw features
generate_features easyrec 模型返回的 FG 之后的特征信息
context_features easyrec 模型返回的上下文特征
item_features item 特征, json string
若有收获,就点个赞吧