PAI-Rec 引擎已经内置了多个过滤模板,包括曝光过滤、状态过滤、数量调整过滤等。
如何配置
过滤的配置对应配置总览中的 FilterConfs,FilterConfs 是一个[]object 结构,可以定义多个过滤策略。
过滤公共配置一览
每种召回配置,都会用到公共配置中的一部分,在此统一解释,单独的召回配置中则不再赘述。
配置示例:
"FilterConfs":[
{
"Name":"",
"FilterType":"",
"Dimension":"",
"DaoConf":{},
"AdjustCountConfs":[{}],
"ItemStateDaoConf":{},
"FilterParams":[{}],
"DiversityDaoConf":{},
"FilterVal":{}
}
]
字段 | 类型 | 是否必填 | 描述 |
Name | string | 是 | 过滤的自定义名称,可以在 FilterNames 中引用 |
FilterType | string | 是 | 引擎内置过滤类型,枚举值,目前支持:
|
Dimension | string | 否 | item 的维度字段 |
DaoConf | DaoConfig | 否 | 数据源表的一些信息 |
AdjustCountConfs | 否 | 优先级数量调整过滤的配置 | |
ItemStateDaoConf | 否 | 状态过滤的配置 | |
FilterParams | 否 | 上下文条件的配置 |
曝光过滤(User2ItemExposureFilter)
很多业务场景都需要曝光过滤来避免重复推荐,这里的曝光过滤其实是伪曝光
伪曝光:因为实时日志有延时等原因,我们并不能立刻知道哪些 item 被曝光,所以我们把推荐引擎返回的 item 列表作为伪曝光列表
目前常用的做法是 PAI-Rec 引擎进行伪曝光的读写,真实曝光需要客户的实时日志,通过 flink 这种实时计算引擎写入数据库,然后被PAI-Rec 引擎消费。
不同数据源的曝光过滤有以下几个公共参数配置
字段名 | 类型 | 是否必填 | 描述 |
Name | string | 是 | 自定义过滤名称 |
FilterType | string | 是 | 过滤类型,固定值 User2ItemExposureFilter |
MaxItems | int | 是 | 获取最近的条目批次数量,相当于 limit ${MaxItems}, MaxItems 这里不是指的具体的 item 数量, 而是批次的概念,也就是说一次推荐请求算作是一次,和一次请求里有多个具体的物料 item 无关 |
TimeInterval | int | 是 | 按照时间戳取最近多长时间内的条目,单位秒 |
WriteLog | bool | 是 | 是否写入曝光日志 |
ClearLogIfNotEnoughScene | string | 否 | 对某个场景下曝光表中的数据进行删除 |
GenerateItemDataFuncName | string | 否 | 构造写入曝光表item数据的函数,为空时,会使用 PAI-Rec内置的函数,内置函数只返回 item_id |
WriteLogExcludeScenes | []string | 否 | 哪些场景不进行曝光日志的写入 |
hologres
"FilterConfs" :[
{
"Name": "holo_exposure_filter",
"FilterType": "User2ItemExposureFilter",
"MaxItems": 100,
"TimeInterval": 172800,
"WriteLog": true,
"DaoConf":{
"AdapterType": "hologres",
"HologresName": "holo_info",
"HologresTableName": "exposure_history"
}
}
]
DaoConf 配置说明
字段 | 类型 | 是否必填 | 描述 |
AdapterType | string | 是 | 数据源的类型,取值 hologres |
HologresName | string | 是 | 在数据源配置(HologresConfs)中配置好的 holo 的自定义名称,如数据源配置中的 holo_info |
HologresTableName | string | 是 | 曝光表名称 |
曝光表定义注意这里可以 按照实际的情况设置 time_to_live_in_seconds 。
BEGIN;
CREATE TABLE "exposure_history" (
"uid" text NOT NULL,
"item" text NOT NULL,
"create_time" int4 NOT NULL,
PRIMARY KEY ("uid","create_time")
);
CALL SET_TABLE_PROPERTY('"exposure_history"', 'orientation', 'column');
CALL SET_TABLE_PROPERTY('"exposure_history"', 'clustering_key', '"uid","create_time"');
CALL SET_TABLE_PROPERTY('"exposure_history"', 'segment_key', '"create_time"');
CALL SET_TABLE_PROPERTY('"exposure_history"', 'bitmap_columns', '"uid","item"');
CALL SET_TABLE_PROPERTY('"exposure_history"', 'dictionary_encoding_columns', '"uid","item"');
CALL SET_TABLE_PROPERTY('"exposure_history"', 'time_to_live_in_seconds', '172800');
comment on table "exposure_history" is '曝光记录表';
COMMIT;
redis
"FilterConfs" :[
{
"Name": "redis_exposure_filter",
"FilterType": "User2ItemExposureFilter",
"MaxItems": 100,
"TimeInterval": 172800,
"WriteLog": true,
"DaoConf":{
"AdapterType": "redis",
"RedisName": "redis_info",
"RedisPrefix": "exposure_"
}
}
]
DaoConf 配置说明
字段 | 类型 | 是否必填 | 描述 |
AdapterType | string | 是 | 数据源的类型,取值 redis |
RedisName | string | 是 | 在数据源配置(RedisConfs)中配置好的 Redis 的自定义名称,如数据源配置中的 redis_info |
RedisPrefix | string | 否 | 曝光数据的 key 前缀,key = RedisPrefix + uid |
tablestore
"FilterConfs" :[
{
"Name": "ots_exposure_filter",
"FilterType": "User2ItemExposureFilter",
"MaxItems": 100,
"TimeInterval": 172800,
"WriteLog": true,
"DaoConf":{
"AdapterType": "tablestore",
"TableStoreName": "tablestore_info",
"TableStoreTableName": "exposure_history"
}
}
]
DaoConf 配置说明
字段 | 类型 | 是否必填 | 描述 |
AdapterType | string | 是 | 数据源的类型,枚举值,如 hologres、mysql、tablestore 等 |
TableStoreName | string | 是 | 在数据源配置(TableStoreConfs)中配置好的 tablestore 的自定义名称,如数据源配置中的 tablestore_info |
TableStoreTableName | string | 是 | 曝光表名称 |
曝光表定义如下:
生命周期:(用户需要自定义,必须有一个明确的周期)
maxVersion: 1
字段 | 类别 | 类型 | 说明 | 示例 |
user_id | 主键 | string | 用户唯一id | 10944750 |
auto_id | 主键 | integer | 自增列 | |
item_ids | 属性 | string | item 唯一id 列表,多个以 ',' 分隔, 如果一次曝光可以包含多个 item_id 的话,可以插入一行数据即可 | 17019277,17019278 |
User2ItemCustomFilter
Hologres
用户需要提供一个自定义的 user2item 的过滤表,进行数据过滤。过滤表一般是离线产出,例如每天凌晨汇总每个用户过去15天看过的物品(即有曝光行为的物品),按照逗号分隔放在一个字段item_ids中。
"FilterConfs" :[
{
"Name": "u2i_custom_filter",
"FilterType": "User2ItemCustomFilter",
"DaoConf": {
"AdapterType": "hologres",
"HologresName": "holo_info",
"HologresTableName": "u2i_custom_filter"
},
"ItemStateCacheSize": 10000,
"ItemStateCacheTime": 3600
}
]
DaoConf 配置说明
字段 | 类型 | 是否必填 | 描述 |
AdapterType | string | 是 | 数据源的类型,固定值 hologres 。 |
HologresName | string | 是 | 在数据源配置(HologresConfs)中配置好的 hologres 的自定义名称,如数据源配置中的 holo_info。 |
HologresTableName | string | 是 | 自定义曝光表名称。 |
ItemStateCacheSize | int | 否 | 开启缓存的情况下,可以缓存的条目数量。如果此值大于0, 默认会开启缓存。 |
ItemStateCacheTime | int | 否 | 开启缓存的情况下,缓存条目的生命周期。默认值为 3600, 单位:秒。 |
表定义如下:
字段 | 类别 | 类型 | 说明 | 示例 |
user_id | 主键 | string | 用户唯一id | 10944750 |
item_ids | 属性 | string | item 唯一id 列表,多个以 ',' 分隔 | 17019277,17019278 |
TableStore(OTS)
用户需要提供一个自定义的 user2item 的过滤表,进行数据过滤。
"FilterConfs" :[
{
"Name": "u2i_custom_filter",
"FilterType": "User2ItemCustomFilter",
"DaoConf":{
"AdapterType": "tablestore",
"TableStoreName": "tablestore_info",
"TableStoreTableName": "u2i_table"
}
}
]
DaoConf 配置说明
字段 | 类型 | 是否必填 | 描述 |
AdapterType | string | 是 | 数据源的类型,固定值 tablestore |
TableStoreName | string | 是 | 在数据源配置(TableStoreConfs)中配置好的 tablestore 的自定义名称,如数据源配置中的 tablestore_info |
TableStoreTableName | string | 是 | 自定义曝光表名称 |
表定义如下:
字段 | 类别 | 类型 | 说明 | 示例 |
user_id | 主键 | string | 用户唯一id | 10944750 |
item_ids | 属性 | string | item 唯一id 列表,多个以 ',' 分隔 | 17019277,17019278 |
数量调整过滤(AdjustCountFilter)
简单的调整数量,把召回数量随机打散,然后保留需要控制的数量。
配置示例:
"FilterConfs" :[
{
"Name": "adjust_count_filter",
"FilterType": "AdjustCountFilter",
"ShuffleItem": true,
"RetainNum": 500
}
]
字段名 | 类型 | 是否必填 | 描述 |
ShuffleItem | string | 是 | 是否打散 |
RetainNum | string | 是 | 打散之后保留的数量 |
优先级数量调整过滤(PriorityAdjustCountFilter)
优先级过滤可以对各路召回进行数量控制,每路召回都会根据召回的 score 进行排序
配置示例:
"FilterConfs" :[
{
"Name": "priority_adjust_count_filter",
"FilterType": "PriorityAdjustCountFilter",
"AdjustCountConfs" :[
{
"RecallName" :"recall_1",
"Count" :125,
"Type" : "accumulator"
},
{
"RecallName" :"recall_2",
"Count" :250,
"Type" : "accumulator"
},
{
"RecallName" :"recall_3",
"Count" :400,
"Type" : "accumulator"
}
]
}
]
字段名 | 类型 | 是否必填 | 描述 |
Name | string | 是 | 自定义的过滤名称 |
FilterType | string | 是 | 过滤类型,固定值 PriorityAdjustCountFilter |
RecallName | string | 是 | 召回源名称 |
AdjustCountConfs | json array | 是 | 优先级配置 |
| int | 是 | 此路召回限制的数量 |
| string | 否 | Type 限制类型,枚举值:accumulator 或 fix。 accumulator 为累加限制。
fix 为固定限制:
|
状态过滤(ItemStateFilter)
我们经常需要对于召回的数据,进行状态过滤。item 的状态有可能会实时变动的,一般会有专有的表存储 item 状态。 此过滤流程需要实时获取 item 状态信息,然后进行过滤。
hologres
"FilterConfs" :[
{
"Name": "ItemStateFilter",
"FilterType": "ItemStateFilter",
"ItemStateDaoConf":{
"AdapterType": "hologres",
"HologresName": "",
"HologresTableName": "",
"ItemFieldName" : "",
"WhereClause": "",
"SelectFields" :""
},
"ItemStateCacheSize": 50000,
"ItemStateCacheTime": 3600,
"FilterParams" :[]
}
]
如果item的状态不经常变化,可以配置缓存选项。
字段名 | 类型 | 是否必填 | 描述 |
ItemStateCacheSize | int | 否 | 要缓存数量。 |
ItemStateCacheTime | int | 否 | 缓存的时间,单位:秒。 |
ItemStateDaoConfig 定义如下:
字段名 | 类型 | 是否必填 | 描述 |
AdapterType | string | 是 | 数据源的类型,枚举值,如 hologres、mysql、tablestore 等 |
HologresName | string | 是 | 在数据源配置(HologresConfs)中配置好的 holo 的自定义名称,如数据源配置中的 holo_info |
HologresTableName | string | 是 | holo 中 item 状态表的表名 |
ItemFieldName | string | 是 | item 状态表的主键 |
WhereClause | string | 否 | 条件过滤语句 |
SelectFields | string | 是 | 需要获取的字段 |
FilterParams 定义如下:
"FilterParams" :[
{
"Name" : "publicStatus",
"Type" : "int",
"Operator" : "equal",
"Value" : 0
},
{
"Name" : "state",
"Type" : "int",
"Operator" : "equal",
"Value" : 1
},
{
"Name" : "checkStatus",
"Type" : "int",
"Operator" : "not_equal",
"Value" : 2
},
{
"Name" : "norec",
"Type" : "int",
"Operator" : "not_equal",
"Value" : 1
}
]
字段名 | 类型 | 是否必填 | 描述 |
Name | string | 是 | 特征名 |
Domain | string | 否 | 特征所属,枚举值:user/item |
Operator | string | 是 | 操作符,支持 equal、not_equal、in, greater , greaterThan , less, lessThan |
Type | string | 是 | 特征的类型 |
Value | object | 是 | 条件值 |
注:WhereClause 和 FilterParams都可以过滤,WhereClause 是在查询的时候过滤,FilterParams是在本地过滤。
具体的 Operator 的使用,可以参考附录。
CompletelyFairFilter
根据召回条目的 score 进行排序,然后公平的从每一路召回获取数据
"FilterConfs" :[
{
"Name": "CompletelyFairFilter",
"FilterType": "CompletelyFairFilter",
"RetainNum": 500
}
]
DimensionFieldUniqueFilter
和 UniqueFilter 不同, 根据 item 的某个字段进行去重过滤
"FilterConfs" :[
{
"Name": "DimensionFieldUniqueFilter",
"FilterType": "DimensionFieldUniqueFilter",
"Dimension":""
}
]
字段名 | 类型 | 是否必填 | 描述 |
Name | string | 是 | 自定义的过滤名称。 |
FilterType | string | 是 | 过滤类型,固定值DimensionFieldUniqueFilter。 |
Dimension | string | 是 | item属性字段,根据这个字段进行去重。如果 item 的这个属性字段为空,则会保留这个item 。 |
UniqueFilter
唯一性过滤,保证 item id 是唯一的,如果两路召回包含同一个 item id,哪路召回先返回,取哪一路的 item id。
无需配置,可直接在 FilterNames 中引用。
如何使用
过滤配置和召回配置类似,配置好之后,提供一个分场景使用的 FilterNames,FilterNames 是一个 Map[string]object 结构,其中 key 是场景,每个场景对应一组过滤策略
"FilterNames": {
"default": [
"UniqueFilter"
]
}
default 为场景名,如果场景没有显式的配置,则使用 "default" 的配置。
UniqueFilter: 此参数为在 FilterConfis 中定义的过滤的自定义名称。
附录
条件匹配 Operator 示例
equal (相等 ==)
{
"Name" : "publicStatus",
"Type" : "int",
"Operator" : "equal",
"Value" : 0
}
not_equal (不等于 !=)
{
"Name" : "checkStatus",
"Type" : "int",
"Operator" : "not_equal",
"Value" : 2
}
greater (大于 >)
{
"Name" : "checkStatus",
"Type" : "int",
"Operator" : "greater",
"Value" : 2
}
greaterThan (大于等于 >=)
{
"Name" : "checkStatus",
"Type" : "int",
"Operator" : "greaterThan",
"Value" : 2
}
less (小于 <)
{
"Name" : "checkStatus",
"Type" : "int",
"Operator" : "less",
"Value" : 2
}
lessThan (小于等于 <=)
{
"Name" : "checkStatus",
"Type" : "int",
"Operator" : "lessThan",
"Value" : 2
}
in (与数组中的某个条目匹配)
{
"Name" : "state",
"Type" : "int",
"Operator" : "in",
"Value" : [2, 4, 6]
}
string 类型
{
"Name" : "state",
"Type" : "string",
"Operator" : "in",
"Value" : ["success", "ok"]
}