在推荐场景下,用户经常需要调整召回策略、排序模型以及模型参数以测试新思路。为此,PAI-Rec开发了一款轻量级A/B测试服务,旨在最小化对现有系统的干扰,并支持快速实验。目前,该服务已提供服务器端的实验功能。
A/B服务介绍
A/B服务主要包括以下组件:
AB Web控制台:作为A/B服务后台管理系统,用于实验配置。数据会持久化到MySQL里。
AB Server:提供HTTP API服务,并部署在PAI-EAS中。该服务从MySQL中读取数据,要求EAS能够直接访问MySQL数据库,确保网络连通性。详情请参见配置网络连通。
AB SDK:需集成到服务端程序中,支持实验配置与流量分配策略。通过SDK可实现请求分流及实验匹配,并依据返回结果采取进一步行动。当前版本支持Go、Python和Java语言。
集成A/B服务实验功能
操作原理
在召回运行时,首先检查是否存在相关的实验参数,如果存在,根据已有的召回实例反射调用 CloneWithConfig方法,并传入实验参数,生成新的召回实例。新生成的召回实例将被注册到系统中。后续调用时,系统将直接返回已注册的实例,避免重复创建。
操作步骤
设置环境
环境值可设为daily、prepub或product,设置方法有两种:
在config.json中配置RunMode。
设置环境变量PAIREC_ENVIRONMENT,其优先级高于config.json中的设置。
配置实验参数
PAI-Rec预先定义了一些实验参数,设置这些参数时必须严格遵守命名规则,否则即使匹配到实验也无法找到相应参数。
参数名称
类型
说明
示例
类目+".RecallNames"
json array
召回的列表,需要包含所有的召回。
"default.RecallNames":[ "HomepageEtrecRecall"**, **"HomepageDssmRecall"]
"recall."+具体的recall name
json object
根据recall config,创建新的recall。
{"recall.MyRecall":{"version":"v2"}}
filterNames
json array
过滤列表,包含所有的过滤流程。
{"filterNames":["UniqueFilter", "UserExposureFilter"]}
rankconf
recconf.RankConfig
排序算法的配置。
"rankconf":{"RankAlgoList":["pai_homepage_fm"],"RankScore":"${pai_homepage_fm}"}
features.scene.name
string
Features load对应的场景名称。
"homepage"
user_features.scene.name
string
User Features预期对应的场景名称。详情请参见User特征预取。
"Home_feed"
类目+".SortNames"
json array
排序模块的列表,需要包含所有排序的模块名称。
"default.SortNames": [
"RetargetDistinctSort",
"RetargetSort",
"TagWeightSort",
"PositionReviseSort",
"DiversitySortHead" ]
"sort."+具体的sort name
json object
根据sort config创建新的sort。
{
"sort.RetargetSortV": {
"Debug": false,
"BoostScoreConditions": [
{
"Conditions": [
{
"Name": "recall_name",
"Domain": "item",
"Type": "string",
"Value": "retarget_u2i",
"Operator": "equal"
}
],
"Expression": "score * 1.0"
}
]
}
}
generalRankConf
recconf.GeneralRankConfig
粗排的配置,包括user feature的获取、算法配置RankConf。具体操作,请参见粗排配置。
{"generalRankConf":{"FeatureLoadConfs":[{"FeatureDaoConf":{}}],"RankConf":{},"ActionConfs":[]}}
coldStartGeneralRankConf
recconf.ColdStartGeneralRankConfig
冷启动粗排配置。具体操作,请参见粗排配置。
{"coldStartGeneralRankConf":{"FeatureLoadConfs":[{"FeatureDaoConf":{}}],"RankConf":{},"ActionConfs":[]}}
coldStartRankConf
recconf.ColdStartRankConfig
冷启动召回,rank阶段配置,指定rank算法。
{"coldStartRankConf":{"RecallName":"ColdStartRecall", "AlgoName":"linucb"}}
匹配实验
每次请求均需匹配实验,并构建上下文。示例代码如下:
func (c *HomeFeedController) makeRecommendContext() { c.context = context.NewRecommendContext() c.context.Size = c.param.Limit c.context.Param = &c.param c.context.RecommendId = c.RequestId c.context.Config = recconf.Config c.context.Debug = c.param.Debug abcontext := model.ExperimentContext{ Uid: c.param.DistinctId, RequestId: c.RequestId, FilterParams: map[string]interface{}{}, } if abtest.GetExperimentClient() != nil { c.context.ExperimentResult = abtest.GetExperimentClient().MatchExperiment(c.param.SceneId, &abcontext) log.Info(c.context.ExperimentResult.Info()) } }
调整实验参数
RecommendContext对象可通过context.ExperimentResult获取特定的实验参数。使用GetLayerParams获取某一层上的实验参数,支持Get、GetInt、GetFloat、GetInt64方法。第一个参数是参数名,第二个参数是默认值,在找不到指定参数时返回默认值。
count := r.recallCount if context.ExperimentResult != nil { count = context.ExperimentResult.GetLayerParams("").GetInt("recall.base.count", count) } fmt.Println("test count", count)
对召回做实验
对于特定的召回做实验时,可通过不同参数动态调整recall配置。需要遵循以下规则:
参数名称格式为:
"recall."+已有的recall name
。参数配置应采用JSON映射形式。
相关召回实例必须实现CloneWithConfig方法,用于基于给定参数生成新的召回实例。例如:
type MyRecall struct { version string } func NewMyRecall() *MyRecall { r := MyRecall{version: "v1"} return &r } func (m *MyRecall) CloneWithConfig(params map[string]interface{}) *MyRecall { r := MyRecall{} if _, ok := params["version"]; ok { r.version = params["version"].(string) } return &r }
集成A/B服务参数功能
使用方式如下:
// 获取到具体的场景名称
scene := context.GetParameter("scene").(string)
// 根据场景获取参数列表,然后用具体的 Get* function 获取具体的参数值
count := abtest.GetParams(scene).GetInt("count", 100)
fmt.Println("recall count:", count)