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 实验动态调整参数,可以在实验中验证不同截断策略的效果
相关文章
|
6月前
|
机器学习/深度学习 分布式计算 搜索推荐
PAI-Rec 召回引擎:构建高性能推荐系统的核心引擎
PAI-Rec是阿里云智能推荐平台的核心召回引擎,经阿里大规模场景验证。支持多路召回融合(U2I/I2I/向量/随机)、召回即过滤、毫秒级实时更新与分布式弹性架构,开箱即用,助力企业构建毫秒级、高精度、强实时的推荐系统。
623 9
|
6月前
|
弹性计算 人工智能 API
阿里云ECS云服务器快速部署OpenClaw实战|千问大模型Qwen3.6-Plus一站式配置教程
随着AI智能体技术不断成熟,OpenClaw(曾用名Clawdbot)已经成为轻量化、可扩展、高稳定性的开源AI执行框架代表。它能够将自然语言指令转化为真实可执行的系统操作、文件处理、信息检索、流程自动化任务,真正实现从“对话”到“执行”的落地。
1206 29
|
5月前
|
缓存 NoSQL Redis
PAI-Rec的RealTimeU2IRecall 如何使用内置的i2i 缓存功能
`RealTimeU2IRecall` 内置物品级本地LRU缓存(I2ICacheSize/I2ICacheTime),对trigger item的相似商品列表进行内存缓存,命中即用、未命中批量查FeatureStore并写入负缓存,兼顾实时性与性能,显著降低下游查询压力。
239 5
|
6月前
|
机器学习/深度学习 搜索推荐 数据处理
PAI-Rec推荐开发平台:企业级智能推荐解决方案,驱动业务全域增长
PAI-Rec是阿里云一站式推荐系统平台,集成多路召回、多目标精排(如DBMTL)、GPU加速推理与灵活迭代能力,已助力电商、直播、音视频等多行业提升点击率、转化率与ROI,实现高效、低成本、可自主演进的智能推荐。
592 16
|
5月前
|
存储 供应链 安全
Gemini 多模态能力在企业云架构中的落地方式
企业落地 Gemini 多模态 API,需要把对象存储、异步任务、模型网关、审核流、日志审计和成本统计一起设计。本文给出一套云上架构拆解。
219 3
|
6月前
|
并行计算 算法框架/工具 iOS开发
TorchRec在macos ARM芯片(Apple Silicon)上无法安装
JaggedTensor等在macOS ARM芯片上无法运行,主因是ARM64与x86_64架构不兼容,且TorchRec深度依赖CUDA——而Apple Silicon仅支持Metal。fbgemm-gpu缺失、Rosetta 2不支持CUDA指令,导致关键操作失败。建议改用MLX框架或标准PyTorch张量替代。
515 4
|
6月前
|
人工智能 运维 安全
Hermes Agent 与 OpenClaw 全面对比:两款热门 AI Agent 框架差异与选型指南
Hermes Agent 与 OpenClaw 是当前开源 AI Agent 领域最受关注的两大框架,二者设计理念、技术路线、能力侧重完全不同,很多用户在选型时容易混淆。本文结合官方定位与实际使用体验,从核心定位、记忆系统、技能机制、安全设计、部署运维、适用场景等维度做完整对比,帮你快速判断哪一款更适合自己。
5627 3
|
人工智能 前端开发 搜索推荐
LangGraph实战教程:构建会思考、能记忆、可人工干预的多智能体AI系统
本文介绍了使用LangGraph和LangSmith构建企业级多智能体AI系统的完整流程。从简单的ReAct智能体开始,逐步扩展至包含身份验证、人工干预、长期内存管理和性能评估的复杂架构。文章详细讲解了状态管理、工具集成、条件流程控制等关键技术,并对比了监督者架构与群体架构的优劣。通过系统化的方法,展示了如何构建可靠、可扩展的AI系统,为现代AI应用开发提供了坚实基础。*作者:Fareed Khan*
3256 0
LangGraph实战教程:构建会思考、能记忆、可人工干预的多智能体AI系统
|
运维 搜索推荐 调度
Ha3搜索引擎简介
Ha3是阿里巴巴搜索团队开发的搜索引擎平台,它为阿里集团包括淘宝、天猫在内的核心业务提供搜索服务支持。
27527 1
|
消息中间件 Docker 索引
【一文解读】阿里自研开源核心搜索引擎 Havenask简介及发展历史
本次分享内容为Havenask的简介及发展历史,由下面五个部分组成(Havenask整体介绍、名词解释、架构、代码结构、编译与部署),希望可以帮助大家更好了解和使用Havenask。
73936 0
【一文解读】阿里自研开源核心搜索引擎 Havenask简介及发展历史