Files
mindfulness/设计说明文档/個性化推薦算法規則.md
2026-02-02 11:22:35 +08:00

13 KiB
Raw Blame History

正念 APP三種分發場景推薦算法方案Feed / Push / Widget · V1

目標 針對三種分發方式Feed、App Push、Widget 每日一句)制定一套一致但可調參的推薦流程。

共用基礎

  • 用戶畫像Umom_stage one-hotemotion/context/need 允许缺失/跳过;含 profile_confidence/profile_answered
  • 文案畫像Cᵢstage、emotion_score、context/need suitability、personalization_power、risk_flags建議含 content_id/author_id/template_id/review_confidence
  • 推薦骨架Hard Filter → Soft Scoring → Rerank多樣性/新鮮度/疲勞)

一、先說整體流程與思路(適用三種場景)

1) 核心理念:同一個用戶同一天需要「不同強度」的個性化

  • Push:最容易翻車 → 高精準 + 低風險Precision-first
  • Widget:每天唯一一句 → 穩定、代表性、可長期持續Consistency-first
  • Feed:可上下滑探索 → 可試探、可擴展、多樣性Exploration-first

2) 共用三段式 Pipeline

  1. Candidate Generation候選集生成

    • 依 U 取一個「候選池」:匹配 need/context/stage 的內容 + 一部分通用內容
    • V1.2:若問卷允許跳過導致 U.need/U.context/U.emotion_score 缺失,候選池需自動提高通用安全內容占比,并视为至少进入 L1限制 personalization_power≤0.5
  2. Hard Filter硬性過濾

    • 依 risk_flags 與產品規則剔除高風險內容
  3. Soft Scoring軟性打分

    • 用加權模型計算核心匹配分
  4. Rerank重排

    • 去重、作者/模板多樣性、頻控、時間衰減
  5. Serve分發

    • 依場景不同策略選 TopK 或組成序列

3) 工程必備:候選不足回退策略 + 可觀測指標V1.1

3.1 候選不足回退Fallback Ladder

目的:避免「過濾/頻控後候選為空」導致體驗斷崖;同時在回退時自動降個性化與降風險(尤其 Push

共用定義:

  • fallback_level:從 0 開始遞增0=不回退)
  • 回退原則:先放寬匹配,再放寬探索,再回退到通用安全池;同時限制 personalization_power 上限

建議梯度(可按場景調整):

  • L0正常:按原候選配比取候選
  • L1放寬匹配need/context1 → ≥0.5personalization_power 上限降為 ≤0.5
  • L2回退通用池:加入更多 general/低風險句;personalization_power 上限降為 0
  • L3兜底:僅從「通用安全句庫」抽取(需單獨維護白名單/安全池)

每次請求需輸出最終使用的 fallback_level(用於分析覆蓋率與風險)。

3.2 可觀測指標(必打點)

每次生成推薦Feed Session / 每次 Push / 每日 Widget至少打點

  • candidate_pool_size_raw:初始候選池大小
  • candidate_pool_size_after_hard_filter
  • candidate_pool_size_after_dedup
  • candidate_pool_size_after_freqcap
  • fallback_level_final
  • served_k:實際下發條數
  • empty_reason:若 served_k=0記錄原因如 hard_filter_all / freqcap_all / pool_empty / unknown

核心監控衍生指標(報表層計算):

  • 覆蓋率served_k > 0 的比例(按場景分開)
  • 回退率fallback_level_final > 0 的比例
  • 頻控後候選數分布candidate_pool_size_after_freqcap 的 P50/P90/P99

二、總分結構Score Decomposition

對任意文案 Cᵢ

[ \textbf{final_score}(U,Cᵢ) = \mathbb{I}[\text{pass filters}] \times \Big( S_{core} + S_{personal} + S_{fresh} - P_{fatigue} - P_{repeat} - P_{risk} - P_{uncertainty} \Big) ]

其中

[ S_{core} = w_{need}S_{need} + w_{emotion}S_{emotion} + w_{stage}S_{stage} + w_{context}S_{context} ]

  • S_need = Cᵢ.need_suitability[U.need](若 U.need 缺失,见 V1.2
  • S_context = Cᵢ.context_suitability[U.context](若 U.context 缺失,见 V1.2
  • S_stagegeneral=1命中=1unknown對非unknown=0.7;其餘=0
  • S_emotion:若文案 general→0.8;否則 1-|U.emotion_score-Cᵢ.emotion_score|(若 U.emotion_score 缺失,见 V1.2

V1.2:当问卷允许跳过题目时的打分约定(工程必读)

目标:用户画像字段不全时仍能产出排序;并在不确定时自动降个性化/降风险。

判定缺失:

  • U.need 为空对象 {} 或不存在 → 视为缺失
  • U.context 为空对象 {} 或不存在 → 视为缺失
  • U.emotion_scorenull/不存在 → 视为缺失

缺失时的保守计算:

  • S_need
    • U.need 缺失 → S_need = 0.5
    • 否则 → S_need = Cᵢ.need_suitability[U.need]
  • S_context
    • U.context 缺失 → S_context = 0.5
    • 否则 → S_context = Cᵢ.context_suitability[U.context]
  • S_emotion
    • U.emotion_score 缺失 → S_emotion = 0.8
    • 否则按原定义计算(文案 general 仍为 0.8

额外约束与回退梯度一致6A

  • conf_U 偏低或字段缺失明显:必须启用 P_uncertainty
  • 若进入回退梯度(fallback_level_final>0):按 L1/L2/L3 限制 personalization_power 上限(见 3.1

個性化加成: [ S_{personal} = \alpha \cdot Cᵢ.personalization_power \cdot \max(S_{need}, S_{context}) ]

不確定性懲罰Push 建議啟用): [ P_{uncertainty} = \beta \cdot (1-\text{conf}U) \cdot (1-\text{conf}{Cᵢ}) \cdot Cᵢ.personalization_power ]

說明:

  • conf_U:用戶畫像置信度(建議由問卷生成後隨時間衰減;見「用戶畫像」文件 V1.1
  • conf_{Cᵢ}:內容標註置信度(Cᵢ.review_confidence;缺省可給 0.7
  • P_{uncertainty} 可併入 P_risk(工程上更簡單),但需保留獨立打點便於調參

三、Hard Filter共用禁推規則

3.1 risk_flags內容自帶

V1.1 起risk_flags 命名/語義以「句子文案打分規則」為準(unsafe_for_* / block_* / soft_*)。

  • U.stage.unknown=1 → 禁推 unsafe_for_stage_unknown
  • U.stage.parenting=1 → 禁推 unsafe_for_stage_parenting
  • U.emotion_score≤0.2 → 禁推 unsafe_for_emotion_low
  • Cᵢ.risk_flagsblock_health_medical全场景禁推Hard Filter(仅挡「医疗/诊断/严重暗示」)

soft_health_sensitive 不做 Hard Filter改由 Soft Penalty見 Push 的 P_risk

3.2 產品規則(跨維度)

  • U.stage.unknown=1Cᵢ.need_suitability[parenting_pressure]=1Cᵢ.personalization_power=1 → 禁推

四、Feed 模式App 內上下滑)— Exploration-first

4.1 目標

  • 讓用戶快速感到「被理解」
  • 同時探索更多題材,避免內容疲乏
  • 允許一定程度的試探(比 Push 寬鬆)

4.2 流程Feed Session

  1. 建候選池(大)

    • 60%:匹配 need/context 的內容(含 personalization_power=0.5/1
    • 30%通用內容general
    • 10%:探索內容(與 context/need 邊緣相關)
  2. Hard Filter仍嚴格

  3. Soft Scoring偏多樣性

  4. Rerank用 MMR 做序列

4.3 Feed 打分權重(建議)

  • w_need=0.35, w_emotion=0.20, w_stage=0.15, w_context=0.30

Feed 更重視「語境共鳴」與內容多樣性,所以 context 權重上調。

4.4 Feed 序列重排MMR

  • Top1最高分確保第一眼命中
  • 後續:在高分候選中,最大化與已選內容的差異(作者/模板/need/context

4.5 Feed 的 MMR 定義工程側定義V1.1

選擇第 t 個內容:

[ \text{MMR}(c)=\lambda \cdot \text{Rel}(c) - (1-\lambda)\cdot \max_{s \in S_{t-1}} \text{Sim}(c,s) ]

建議預設:λ = 0.7(更偏相關性,仍保留多樣性)

  • Rel(c):使用 final_score(U,c)(或 Soft Scoring 後的分數)
  • Sim(c,s):相似度定義(無 embedding 也可落地)

相似度(離散特徵版,推薦 V1 上線):

  • content_id 相同 → Sim=1
  • template_id 相同且非空 → Sim += 0.6
  • author_id 相同且非空 → Sim += 0.3
  • need/context/stage 標籤重合JaccardSim += 0.1 * Jaccard(tags_c, tags_s)
  • 最終 Sim clamp 到 [0,1]

字段依賴與回退:

  • template_id/author_id 時,只用 tags 相似度Sim 仍可算)
  • 若後續引入文本 embedding可將 embedding cosine 加權合併V2

五、App Push可設定 05 次)— Precision & Safety-first

5.1 目標

  • Push 是「打擾」:錯一次就掉留存
  • 追求「準、溫柔、少翻車」

5.2 流程(每次 Push

  1. 候選池(小而精)

    • 70%need 命中S_need=1的內容
    • 20%emotion 命中(距離小)的內容
    • 10%通用安全句general + 低風險)
  2. Hard Filter最嚴格

  3. Soft Scoring偏 need + emotion

  4. 冷卻與頻控(必做)

    • 同一句/同作者/同模板至少 X 天不重複
  5. 發送

Push 追加規則V1.1):若 fallback_level_final > 0conf_U 偏低,需自動「降個性化」:

  • personalization_power 上限降為 ≤0.5L10L2/L3
  • 若候選不足,優先回退到「通用安全句庫」,而不是擴大高個性化內容

V1.2(支持问卷跳过)补充:

  • profile_answered.need=falseU.need 缺失不得按“need 强命中”召回,候选池应提高通用安全句占比,并至少按 L1 降个性化
  • profile_answered.emotion=falseU.emotion_score 缺失Push 应偏向 Cᵢ.emotion_scoregeneral 或 0.40.8 的稳定内容,并启用 P_uncertainty

5.3 Push 打分權重(建議)

  • w_need=0.45, w_emotion=0.35, w_stage=0.15, w_context=0.05

Push 更在乎「此刻需要」與「語氣安全」。context 權重降低。

5.4 Push 風險懲罰P_risk

  • Cᵢ.personalization_power=1S_need<1S_context<1 → 額外扣分
  • 若 content 涉及健康敏感(soft_health_sensitive)→ 扣分Soft Penalty不做禁推
  • 不確定性懲罰:P_uncertainty(或併入 P_risk),用於在 conf_U/conf_C 偏低時自動降權高個性化內容

5.5 05 次推送的排程策略

  • 使用者設定次數 N

    • 第 1 條need 命中 + 安全
    • 第 2 條emotion 修復
    • 第 3 條self-worth / rest_balance視 need 而定)
    • 第 45 條:通用句補位,避免疲勞

六、Widget每日一句— Consistency & Brand-first

6.1 目標

  • Widget 是「代表你這個 App 的一句話」
  • 需要:穩定、可持續、低風險、避免太私密

6.2 流程(每日生成)

  1. 候選池:以 general + personalization_power≤0.5 為主
  2. Hard Filter嚴格
  3. Soft Scoring偏 stage 安全 + emotion 中性/平靜
  4. 跨日多樣性7 日內不重複作者/模板/同一句

若候選不足:同樣走回退梯度(優先增加 general 安全句;不提高個性化力度)。

6.3 Widget 打分權重(建議)

  • w_need=0.25, w_emotion=0.25, w_stage=0.30, w_context=0.20

Widget 需要「身份語境安全」與「普適」stage 權重更高。

6.4 Widget 的情緒區間約束

  • 建議限制 Cᵢ.emotion_score0.40.8tired→calm

    • 避免太低(沉重)
    • 避免太高(過嗨)

七、場景差異總結(快速對照)

場景 目標 候選池 風險容忍 權重重點 序列策略
Feed 探索+共鳴 context↑、diversity↑ MMR 序列
Push 準+安全 need↑、emotion↑ 頻控+冷卻
Widget 穩+代表性 中小 stage↑、emotion中性 跨日多樣性

八、(後段解釋預告)提及的算法/概念

  • Candidate Generation混合召回命中 + 通用 + 探索)
  • Hard Filter規則引擎
  • Linear Weighted Scoring加權線性模型
  • MMRMaximal Marginal Relevance多樣性重排
  • Time Decay時間衰減
  • Frequency Capping頻控
  • Cooldown Keys去重鍵句子/作者/模板)

工程側去重鍵定義V1.1

  • sentence_key = content_id(若無 content_id需生成 stable hash但建議補 content_id
  • author_key = author_id(可空)
  • template_key = template_id(可空)

冷卻/頻控同時支持三層 key避免只靠單一 key 造成過度重複或過度稀釋。


九、V1 可直接上線的預設參數

  • FeedTop1 命中 + MMR 序列 30 條
  • Push每次 Top1冷卻 7 天不重複作者14 天不重複同句
  • Widgetemotion_score 限制 0.40.87 日不重複作者/模板

V1.1 補充(工程預設):

  • FeedMMR λ=0.7
  • Push啟用 P_uncertainty(或併入 P_riskfallback_level>=1personalization_power 上限降為 ≤0.5
  • Healthblock_health_medical 全场景 Hard Filtersoft_health_sensitive 走 Soft Penalty

一句話: 同一套 U×Cᵢ 打分,按場景調候選池、權重與重排約束。