PAI-Rec 多路召回截断实践:用 PriorityAdjustCountFilter 和 SnakeFilter 控制精排入口数量

简介: PAI-Rec推荐开发平台提供PriorityAdjustCountFilter(按优先级截取)与SnakeFilter(按权重蛇形交错)两种多路召回截断策略,无需粗排即可将数百候选精准压缩至200个以内进入精排,兼顾保量性、多样性与业务可控性。

背景

在推荐系统中,多路召回会产生大量候选 item。如果不使用粗排(General Rank),这些候选会直接进入精排模型打分,带来较大的计算开销和延迟。

PAI-Rec 提供了两个过滤器来解决这个问题:

  • PriorityAdjustCountFilter:按优先级截取各路召回,保证高优先级召回路的 item 优先入选
  • SnakeFilter:按权重蛇形交错分配各路召回,保证各路 item 均匀混合

两者都能在不使用粗排的情况下,将多路召回的数百甚至上千个候选压缩到指定数量(如 200 个),再进入精排。


一、PriorityAdjustCountFilter —— 按优先级截取

核心逻辑

  1. 将所有候选 item 按 RetrieveId(召回路名称)分组
  2. 按配置顺序(即优先级)从高到低,依次从每路中取 N 个 item
  3. 每路内部按 Score 降序排列,优先取高分 item
  4. 支持两种计数模式:
    • fix:每路固定取 N 个
    • accumulator:累计取满 N 个后停止

配置示例

{
   
  "FilterConfs": [
    {
   
      "Name": "priority_truncate",
      "FilterType": "PriorityAdjustCountFilter",
      "AdjustCountConfs": [
        {
   
          "RecallName": "u2i_recall",
          "Type": "fix",
          "Count": 80
        },
        {
   
          "RecallName": "vector_recall",
          "Type": "fix",
          "Count": 60
        },
        {
   
          "RecallName": "hot_recall",
          "Type": "fix",
          "Count": 40
        },
        {
   
          "RecallName": "new_recall",
          "Type": "fix",
          "Count": 20
        }
      ]
    }
  ]
}

效果:从 u2i 取 80 个 → 向量召回取 60 个 → 热门取 40 个 → 新品取 20 个,总共 200 个进入精排。

累计模式配置

如果希望"总共不超过 200 个,按优先级依次填充":

{
   
  "FilterConfs": [
    {
   
      "Name": "priority_truncate_acc",
      "FilterType": "PriorityAdjustCountFilter",
      "AdjustCountConfs": [
        {
   
          "RecallName": "u2i_recall",
          "Type": "accumulator",
          "Count": 100
        },
        {
   
          "RecallName": "vector_recall",
          "Type": "accumulator",
          "Count": 160
        },
        {
   
          "RecallName": "hot_recall",
          "Type": "accumulator",
          "Count": 200
        }
      ]
    }
  ]
}

效果:先从 u2i 取最多 100 个;再从 vector_recall 取,累计到 160 个;最后从 hot_recall 补满到 200 个。如果前面的路数量不够,后面的路会多取。

适用场景

  • 各路召回有明确优先级(如个性化召回 > 热门召回)
  • 希望保证核心召回路的候选数量不被稀释
  • 对各路占比有确定性要求

二、SnakeFilter —— 按权重蛇形交错分配

核心逻辑

  1. 根据各路的 Weight 按比例计算每路应分配的 item 数量
  2. 按"蛇形"方式轮流从各路取 item:每轮按权重值取对应个数
  3. 各路内部按 Score 降序排列
  4. 遇到重复 item(被多路召回的同一物品),支持两种策略:
    • REFILL_ON_DUPLICATE(默认):跳过重复 item 但不消耗配额,继续取下一个
    • SKIP_ON_DUPLICATE:跳过重复 item 且消耗配额

配置示例

{
   
  "FilterConfs": [
    {
   
      "Name": "snake_truncate",
      "FilterType": "SnakeFilter",
      "RetainNum": 200,
      "AdjustCountConfs": [
        {
   
          "RecallName": "u2i_recall",
          "Weight": 4
        },
        {
   
          "RecallName": "vector_recall",
          "Weight": 3
        },
        {
   
          "RecallName": "hot_recall",
          "Weight": 2
        },
        {
   
          "RecallName": "new_recall",
          "Weight": 1
        }
      ]
    }
  ]
}

效果:总共保留 200 个候选,按 4:3:2:1 的比例分配。蛇形交错取出,最终结果中:

  • u2i_recall 约 80 个
  • vector_recall 约 60 个
  • hot_recall 约 40 个
  • new_recall 约 20 个

输出结果的排列顺序是交错的(每轮 u2i 取 4 个 → vector 取 3 个 → hot 取 2 个 → new 取 1 个),有利于后续排序的多样性。

SKIP_ON_DUPLICATE 模式

当一个 item 被多路召回同时命中时,默认模式会让它"不占坑位"(即不消耗当前路的配额),如果你希望严格按权重分配坑位数(即使遇到重复也消耗配额),可以设置:

{
   
  "FilterConfs": [
    {
   
      "Name": "snake_truncate_skip",
      "FilterType": "SnakeFilter",
      "RetainNum": 200,
      "SnakeType": "SKIP_ON_DUPLICATE",
      "AdjustCountConfs": [
        {
   
          "RecallName": "u2i_recall",
          "Weight": 4
        },
        {
   
          "RecallName": "vector_recall",
          "Weight": 3
        }
      ]
    }
  ]
}

适用场景

  • 各路召回没有明确优先级,希望"雨露均沾"
  • 希望最终候选的多样性更好(交错排列)
  • 各路召回重叠较多,需要合理去重分配

三、完整配置示例:两者组合使用

在实际业务中,可以组合使用:先用 PriorityAdjustCountFilter 做初步截断(如从 1000 降到 400),再用 SnakeFilter 做精确的权重分配(从 400 降到 200)。

{
   
  "FilterConfs": [
    {
   
      "Name": "exposure_filter",
      "FilterType": "User2ItemExposureFilter",
      "TimeInterval": 300,
      "WriteLog": true,
      "DaoConf": {
   
        "AdapterType": "featurestore",
        "FeatureStoreName": "fs_pairec",
        "FeatureStoreViewName": "user_expose"
      }
    },
    {
   
      "Name": "priority_truncate",
      "FilterType": "PriorityAdjustCountFilter",
      "AdjustCountConfs": [
        {
   
          "RecallName": "u2i_recall",
          "Type": "accumulator",
          "Count": 150
        },
        {
   
          "RecallName": "vector_recall",
          "Type": "accumulator",
          "Count": 280
        },
        {
   
          "RecallName": "hot_recall",
          "Type": "accumulator",
          "Count": 350
        },
        {
   
          "RecallName": "new_recall",
          "Type": "accumulator",
          "Count": 400
        }
      ]
    },
    {
   
      "Name": "snake_truncate",
      "FilterType": "SnakeFilter",
      "RetainNum": 200,
      "AdjustCountConfs": [
        {
   
          "RecallName": "u2i_recall",
          "Weight": 4
        },
        {
   
          "RecallName": "vector_recall",
          "Weight": 3
        },
        {
   
          "RecallName": "hot_recall",
          "Weight": 2
        },
        {
   
          "RecallName": "new_recall",
          "Weight": 1
        }
      ]
    }
  ],

  "FilterNames": {
   
    "home_feed": ["exposure_filter", "priority_truncate", "snake_truncate"]
  }
}

执行流程

多路召回 (1000+ items)
    ↓
曝光过滤 (去除已曝光)
    ↓
PriorityAdjustCountFilter (按优先级截取到 400)
    ↓
SnakeFilter (按权重蛇形分配到 200)
    ↓
精排模型打分 (200 items)
    ↓
重排/多样性调控
    ↓
返回结果

四、关键配置字段说明

PriorityAdjustCountFilter

字段 类型 说明
FilterType string 固定值 "PriorityAdjustCountFilter"
AdjustCountConfs array 各路召回的截取规则,顺序即优先级
AdjustCountConfs[].RecallName string 召回路名称,对应 RecallConfs 中的 Name
AdjustCountConfs[].Type string "fix" = 每路固定数量;"accumulator" = 累计到指定数量
AdjustCountConfs[].Count int fix 模式下为该路取的数量;accumulator 模式下为累计上限
EnsureDiversity bool 是否在截取时保证多样性(需配合 DiversityDaoConf

SnakeFilter

字段 类型 说明
FilterType string 固定值 "SnakeFilter"
RetainNum int 最终保留的候选总数
SnakeType string 重复处理策略:空(默认)= REFILL_ON_DUPLICATE"SKIP_ON_DUPLICATE"
AdjustCountConfs array 各路召回的权重配置
AdjustCountConfs[].RecallName string 召回路名称
AdjustCountConfs[].Weight int 权重值,决定各路分配的比例

五、两者的对比与选择

维度 PriorityAdjustCountFilter SnakeFilter
分配策略 按优先级顺序截取 按权重比例蛇形交错
输出顺序 按路分块(先 A 路全部,再 B 路全部) 交错排列(A B C A B C ...)
重复 item 处理 RetrieveId 分组,多路命中的 item 只归属一路 支持多路共享同一 item,配额可配
总数控制 通过最后一条 accumulator 的 Count 间接控制 通过 RetainNum 直接控制
多样性 可选 EnsureDiversity 配合多样性约束 天然交错,多样性较好
适合场景 有明确优先级,核心路必须保量 各路平等,追求均匀混合

推荐选择

  • 只需要简单截断:用 PriorityAdjustCountFilter,配置直观
  • 需要均匀混合+精确总数控制:用 SnakeFilter
  • 两者组合:先用 PriorityAdjustCountFilter 粗截(高优保量),再用 SnakeFilter 精细分配(权重混合)

六、注意事项

  1. 过滤顺序:在 FilterNames 中,截断过滤器应放在曝光过滤、状态过滤之后,确保先去掉无效 item 再截断
  2. RecallName 匹配AdjustCountConfs 中的 RecallName 必须与 RecallConfs 中召回的 Name 完全一致
  3. 未配置的召回路:如果某路召回未在 AdjustCountConfs 中配置,其 item 会被直接丢弃(不会进入最终结果)
  4. 候选不足时:如果某路的实际 item 数不够配额,会取尽该路所有 item,不会报错
  5. 精排数量规划RetainNum / 最终 Count 应根据精排模型的 QPS 和延迟要求来设置,通常 100~300 是合理范围
  6. 实验参数:两个过滤器都支持通过 AB 实验动态调整参数,可以在实验中验证不同截断策略的效果
相关文章
|
2月前
|
弹性计算 人工智能 API
阿里云ECS云服务器快速部署OpenClaw实战|千问大模型Qwen3.6-Plus一站式配置教程
随着AI智能体技术不断成熟,OpenClaw(曾用名Clawdbot)已经成为轻量化、可扩展、高稳定性的开源AI执行框架代表。它能够将自然语言指令转化为真实可执行的系统操作、文件处理、信息检索、流程自动化任务,真正实现从“对话”到“执行”的落地。
886 29
|
26天前
|
人工智能 供应链 安全
2026 年全球网络安全威胁态势与关键技术防御研究
本文基于Security Affairs 2026年第576期情报,系统分析Linux无文件远控(QLNX)、Dirty Frag内核提权、AI供应链投毒、Bluekit工业化钓鱼及关键基础设施混合攻击等新型威胁,揭示其内存化、智能化、武器化趋势;提出漏洞治理、供应链管控、钓鱼防御、终端加固、应急响应“五位一体”纵深防御框架,并提供可复现代码与工程化方案。(239字)
476 6
|
7天前
|
机器学习/深度学习 人工智能 网络架构
深度解析:Transformer 的“灵魂”——QKV 变换的物理直觉
本文用图书馆检索等生活隐喻,从物理意义与认知科学角度解析Transformer中QKV设计的精妙本质:解耦查询(q)、键(k)、值(v)三重角色,实现语义分离、避免自注意力“自恋”,模拟人类动态信息路由的认知过程。(239字)
195 13
|
2月前
|
机器学习/深度学习 分布式计算 搜索推荐
PAI-Rec 召回引擎:构建高性能推荐系统的核心引擎
PAI-Rec是阿里云智能推荐平台的核心召回引擎,经阿里大规模场景验证。支持多路召回融合(U2I/I2I/向量/随机)、召回即过滤、毫秒级实时更新与分布式弹性架构,开箱即用,助力企业构建毫秒级、高精度、强实时的推荐系统。
339 9
|
7天前
|
存储 搜索推荐 大数据
优路教育借助阿里云Flink+StarRocks+Paimon湖仓一体化构建职业教育业务全链路实时数据服务平台
优路教育大数据团队携手阿里云,基于实时计算 Flink + EMR Serverless StarRocks + DLF(Paimon) 构建了全链路实时数据服务平台,从学员画像、营销筛选到题库关联查询,实现了从“分钟级延迟”到“秒级响应”的质变,为成人教育行业的数据化转型提供了标杆实践。
|
7天前
|
人工智能 机器人 芯片
人工智能|YOLOv8实战
本内容为安全帽检测实战项目,基于YOLOv8模型,涵盖Kaggle数据获取、自定义yaml配置、模型训练(yolo_train.py)与测试(yolo_test.py),并提供服务器(FastAPI+Docker)、边缘(Jetson+TensorRT)及国产嵌入式(RK3588+RKNN)三类部署方案,支持工业场景实时智能识别。(239字)
148 1
|
2月前
|
存储 人工智能 安全
深度解析 OpenClaw 在 Prompt / Context / Harness 三个维度中的设计哲学与实践
本文的核心思路是从Prompt、Context和Harness这三个维度展开,分析OpenClaw的设计思路,提炼出其中可复用的方法论,来思考如何将这些精华的设计哲学应用到我们自己的Agent系统设计和业务落地中去。(文章内容基于作者个人技术实践与独立思考,旨在分享经验,仅代表个人观点。)
1803 38
深度解析 OpenClaw 在 Prompt / Context / Harness 三个维度中的设计哲学与实践
|
6天前
|
存储 人工智能 算法
告别无效刷屏!TrendRadar:最快30秒部署的开源热点助手,让你只看真正关心的新闻
TrendRadar 是一个轻量级、易部署的热点新闻聚合与推送工具。它能够从知乎、抖音、B站、微博、百度、华尔街见闻等11个主流平台抓取热搜榜单,然后根据你设定的关键词进行智能筛选,最终将你最关心的内容推送到手机或邮箱。
169 13
 告别无效刷屏!TrendRadar:最快30秒部署的开源热点助手,让你只看真正关心的新闻
|
7天前
|
人工智能 供应链 数据可视化
长江商学院CIO徐斌:AI时代,组织的进化逻辑与人才转型新思维
徐斌,长江商学院CIO、计算机博士,20年世界500强及上市公司高管经验,首创数字化“三驾马车”方法论(流程变革、IT固化、数字运营),成功主导得力集团全链路转型,助力其获评首批浙江省未来工厂。
|
6天前
|
机器学习/深度学习 数据采集 人工智能
田间杂草检测数据集分享(适用于YOLO系列深度学习分类检测任务)
本数据集含4000张真实农田图像(小麦/玉米/水稻田),YOLO格式标注杂草目标,覆盖多天气、光照与视角,适用于YOLO系列等目标检测模型训练,助力智能除草与精准农业研究。(239字)
183 16