全部產品
Search
文件中心

Artificial Intelligence Recommendation:通過推薦過濾功能實現Feed流個人化過濾

更新時間:May 13, 2025

本文將向您介紹如何使用推薦過濾功能,實現推薦情境的按需定製,滿足使用者的特定瀏覽喜好。

一、背景介紹

在某些猜你喜歡情境當中,使用者可能會出於需求或自身喜好與經驗,只想要看到屬於特定品牌等擁有特定屬性的物品,此時可以使用推薦過濾功能,只要在用戶端埋點對應選擇邏輯,在服務端SDK請求推薦結果時加上要篩選的條件,即可擷取到希望返回的指定類型(比如指定類別、標籤、城市、作者等等)的物品。

實現情境:

以下為使用情境

例1:

當使用者在瀏覽民宿、酒店時,對地點等屬性有硬性需求,此時就可以選擇對應需求的tag來篩選推薦結果,讓使用者可以更加方便快捷的找到心儀的物品。(此功能同樣也可適用於行為資料較少的新使用者,通過使用者自身選擇來快速鎖定使用者喜好。)

推薦過濾1

例2:

新品活動頁面篩選使用者喜好品牌的活動產品:

推薦過濾2

使用者在瀏覽新品推薦的情境時,想要對自己感興趣的品牌進行過濾篩選。

可以看到,該功能可在部分已有情境(如新品、活動商品)的基礎上,疊加使用者根據自己喜好選擇的過濾條件,形成更加靈活、細分、可自由定製的個人化推薦結果。

二、使用方法

推薦過濾功能目前沒有控制台設定頁面,因為是在已有推薦情境的基礎上增加對物品屬性的過濾, 因此需要在請求推薦結果時,以添加參數的形式調用請求推薦結果的介面使用,具體方式為:

將表示過濾規則的JSON字串經過Base64編碼後,將編碼結果中的”+”、”/” 、”=”分別替換為”-”、”_” 、”.”,然後將此結果作為filter參數,請求推薦介面即可。

重要

除了要求符合基本格式外,過濾規則中還要求:

  1. 總的單值過濾規則不超過10個

  2. 組合深度不超過3層(即第3層的所有過濾規則必須都是單值過濾規則)

  3. 阿里雲對URL的長度有限制,因此編碼之後的字串總長度不能過長,否則可能會引起SDK拋錯;

    一般來說,只要遵循上述1、2要求,這個長度都不會超過限制。

此處SDK樣本位於文章末尾。

三、功能詳解

推薦過濾功能支援對物品的單個屬性欄位的單值過濾,也支援對多個屬性欄位的組合過濾。

單值過濾:

支援的過濾條件有三種類型:

  1. 包含/不包含(contain/not_contain),僅支援多重值欄位(多重值欄位是指可以用逗號分隔的字串欄位,比如tags, author)

  2. 相等/不相等(equal/not_equal,僅支援單值欄位(比如item_type, title, city)

  3. 類目匹配/類目不匹配(category_match/category_not_match),僅支援類目欄位(只有category_path),類目匹配只支援從頭開始,比如category_path=1_2_3_4,則只能匹配1、1_2、1_2_3、1_2_3_4,而不能匹配2_3、 3_4、2_3_4)

組合過濾:

對單值過濾或其他組合過濾的結果進行“且/或”的邏輯組合。 目前不同行業支援的推薦過濾欄位有所差異,具體支援推薦過濾的欄位如下:

  1. 電商行業:

    單值欄位:

    item_id,item_type,category_level,category_path,weight,cur_price,brand_id,shop_id,source_id

    多重值欄位:

    tags

  2. 內容行業: 單值欄位:

    item_id,item_type,category_level,category_path,channel,weight,pub_id,source_id,country,city

    多重值欄位:

    tags,organization,author

  3. 新聞行業: 單值欄位:

    item_id,item_type,category_level,category_path,channel,weight,pub_id,source_id,country,city

    多重值欄位:

    tags,organization,author

過濾規則通過一個JSON字串來表示,JSON格式的過濾規則的具體文法如下: 單值過濾:

{
                "cond": "contain" | "not_contain" | "equal" | "not_equal"| "category_match" | "category_not_match", // 要進行的比較操作
                "field": "<field_name>", // 要篩選的欄位名,如"tags"、"channel"等
                "value": "<compare_value>" // 要篩選的目標值,如"軍事"、"周星馳"等
}

組合過濾:

{
                "join": "and" | "or",
                "filters": [
                                { 組合過濾規則 | 單值過濾規則 },
                                { 組合過濾規則 | 單值過濾規則 },
                                ...
                ]
}

四、應用執行個體

例3:

如圖,假設當前產品為旅遊類電商,情境設定有“出行”、“酒店”等情境,其中“出行”情境中設定了“機票”、“火車票”、“汽車/船票”、“接送/租車”四個類目(category_path)的物品(item)。

使用者想要查看“出行”頁面下,“接送/租車”類目裡的“租車”物品,

使用者有額外需求是:能送車上門、是京牌、有倒車雷達,

根據需求,此處需要擷取推薦商品的請求為:在“出行_接送/租車”類目下,屬於“租車”類(假設用brand_id區分)的商品,但因使用者有額外需求,則需要使用到組合過濾功能,來滿足使用者一定的定製需求。

假設後面三項需求是在物品的tags欄位中作為屬性存放,則此處的推薦過濾運算式為:

( category_path 類目匹配 “出行_接送/租車 )AND ( brand_id = “租車”) AND

((tags 包含 “送車上門”) OR (tags 包含 “京牌”) OR (tags 包含 “倒車雷達”))

可用如下JSON格式的過濾條件查詢:

{
  "join": "and",
  "filters": [
  {
    "cond": "contain",
    "field": "brand_id",
    "value": "租車"
  },
  {
    "cond": "category_match",
    "field": "category_path",
    "value": "出行_接送/租車"
  },
  {
      "join": "or",
    "filters": [{
      "cond": "contain",
      "field": "tags",
      "value": "送車上門"
    },
    {
      "cond": "contain",
      "field": "tags",
      "value": "京牌"
    },
    {
      "cond": "contain",
      "field": "tags",
      "value": "倒車雷達"
    }]
  }]
}

在發送請求時,使用如上的過濾條件即可。

說明

在field相同的情況下可以進行簡寫,and用&,or用|串連。例如“送車上門”、“京牌”與“倒車雷達”的field都為tags,即可用"送車上門|京牌|倒車雷達"表示。

{
  "join": "and",
  "filters": [
  {
    "cond": "contain",
    "field": "brand_id",
    "value": "租車"
  },
  {
    "cond": "category_match",
    "field": "category_path",
    "value": "出行_接送/租車"
  },
  {
      "cond": "contain",
      "field": "tags",
      "value": "送車上門|京牌|倒車雷達"
  }]
}

SDK調用代碼範例

SDK調用程式碼範例:

@Data
private static abstract class BaseFilterRule {}

@EqualsAndHashCode(callSuper = true)
@Data
private static final class JoinFilterRule extends BaseFilterRule {
    String join;
    List<BaseFilterRule> filters = new ArrayList<>();
}

@EqualsAndHashCode(callSuper = true)
@Data
private static final class SingleFilterRule extends BaseFilterRule {
    String cond;
    String field;
    String value;
}

public void testRecommendWithFilterDemo() throws ClientException {
    JoinFilterRule rootRule = new JoinFilterRule();
    rootRule.setJoin("and");
    {
        JoinFilterRule tagsRule = new JoinFilterRule();
        tagsRule.setJoin("or");
        {
            SingleFilterRule rule = new SingleFilterRule();
            rule.setCond("contain");
            rule.setField("tags");
            rule.setValue("小紅書");
            tagsRule.getFilters().add(rule);
        }
        {
            SingleFilterRule rule = new SingleFilterRule();
            rule.setCond("contain");
            rule.setField("tags");
            rule.setValue("爆品");
            tagsRule.getFilters().add(rule);
        }
        rootRule.getFilters().add(tagsRule);
    }
    {
        SingleFilterRule rule = new SingleFilterRule();
        rule.setCond("equal");
        rule.setField("channel");
        rule.setValue("美妝");
        rootRule.getFilters().add(rule);
    }
    {
        SingleFilterRule rule = new SingleFilterRule();
        rule.setCond("not_equal");
        rule.setField("category");
        rule.setValue("促銷品");
        rootRule.getFilters().add(rule);
    }
    {
        SingleFilterRule rule = new SingleFilterRule();
        rule.setCond("category_match");
        rule.setField("category_path");
        rule.setValue("女裝_裙子");
        rootRule.getFilters().add(rule);
    }
    String filterRuleString = new Gson().toJson(rootRule);
    filterRuleString = new String(Base64.getEncoder().encode(filterRuleString.getBytes()));
    filterRuleString = filterRuleString.replaceAll("\\+", "-");
    filterRuleString = filterRuleString.replaceAll("/", "_");
    filterRuleString = filterRuleString.replaceAll("=", ".");
    DefaultAcsClient client = createClient();
    RecommendRequest request = new RecommendRequest();
    request.setInstanceId(instanceId);
    request.setSceneId(sceneId);
    request.setUserId(userId);
    request.putQueryParameter("filter", filterRuleString);  //  添加filter參數 
    request.setReturnCount(2);
    request.setAcceptFormat(FormatType.JSON);
    RecommendResponse response = client.getAcsResponse(request);
    System.out.println(String.format("got %d results", response.getResult().size()));
}