13 KiB
正念 APP|三種分發場景推薦算法方案(Feed / Push / Widget · V1)
目標: 針對三種分發方式(Feed、App Push、Widget 每日一句)制定一套一致但可調參的推薦流程。
共用基礎:
- 用戶畫像:U(mom_stage one-hot;emotion/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
-
Candidate Generation(候選集生成)
- 依 U 取一個「候選池」:匹配 need/context/stage 的內容 + 一部分通用內容
- V1.2:若問卷允許跳過導致
U.need/U.context/U.emotion_score缺失,候選池需自動提高通用安全內容占比,并视为至少进入 L1(限制personalization_power≤0.5)
-
Hard Filter(硬性過濾)
- 依 risk_flags 與產品規則剔除高風險內容
-
Soft Scoring(軟性打分)
- 用加權模型計算核心匹配分
-
Rerank(重排)
- 去重、作者/模板多樣性、頻控、時間衰減
-
Serve(分發)
- 依場景不同策略選 TopK 或組成序列
3) 工程必備:候選不足回退策略 + 可觀測指標(V1.1)
3.1 候選不足回退(Fallback Ladder)
目的:避免「過濾/頻控後候選為空」導致體驗斷崖;同時在回退時自動降個性化與降風險(尤其 Push)。
共用定義:
fallback_level:從 0 開始遞增(0=不回退)- 回退原則:先放寬匹配,再放寬探索,再回退到通用安全池;同時限制
personalization_power上限
建議梯度(可按場景調整):
- L0(正常):按原候選配比取候選
- L1(放寬匹配):
need/context由1 → ≥0.5;personalization_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_filtercandidate_pool_size_after_dedupcandidate_pool_size_after_freqcapfallback_level_finalserved_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_stage:general=1;命中=1;unknown對非unknown=0.7;其餘=0S_emotion:若文案 general→0.8;否則1-|U.emotion_score-Cᵢ.emotion_score|(若 U.emotion_score 缺失,见 V1.2)
V1.2:当问卷允许跳过题目时的打分约定(工程必读)
目标:用户画像字段不全时仍能产出排序;并在不确定时自动降个性化/降风险。
判定缺失:
U.need为空对象{}或不存在 → 视为缺失U.context为空对象{}或不存在 → 视为缺失U.emotion_score为null/不存在 → 视为缺失
缺失时的保守计算:
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_unknownU.stage.parenting=1→ 禁推unsafe_for_stage_parentingU.emotion_score≤0.2→ 禁推unsafe_for_emotion_lowCᵢ.risk_flags含block_health_medical→ 全场景禁推(Hard Filter)(仅挡「医疗/诊断/严重暗示」)
soft_health_sensitive不做 Hard Filter,改由 Soft Penalty(見 Push 的 P_risk)
3.2 產品規則(跨維度)
U.stage.unknown=1且Cᵢ.need_suitability[parenting_pressure]=1且Cᵢ.personalization_power=1→ 禁推
四、Feed 模式(App 內上下滑)— Exploration-first
4.1 目標
- 讓用戶快速感到「被理解」
- 同時探索更多題材,避免內容疲乏
- 允許一定程度的試探(比 Push 寬鬆)
4.2 流程(Feed Session)
-
建候選池(大)
- 60%:匹配 need/context 的內容(含 personalization_power=0.5/1)
- 30%:通用內容(general)
- 10%:探索內容(與 context/need 邊緣相關)
-
Hard Filter(仍嚴格)
-
Soft Scoring(偏多樣性)
-
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標籤重合(Jaccard)→Sim += 0.1 * Jaccard(tags_c, tags_s)- 最終
Simclamp 到[0,1]
字段依賴與回退:
- 缺
template_id/author_id時,只用 tags 相似度(Sim 仍可算) - 若後續引入文本 embedding,可將 embedding cosine 加權合併(V2)
五、App Push(可設定 0–5 次)— Precision & Safety-first
5.1 目標
- Push 是「打擾」:錯一次就掉留存
- 追求「準、溫柔、少翻車」
5.2 流程(每次 Push)
-
候選池(小而精)
- 70%:need 命中(S_need=1)的內容
- 20%:emotion 命中(距離小)的內容
- 10%:通用安全句(general + 低風險)
-
Hard Filter(最嚴格)
-
Soft Scoring(偏 need + emotion)
-
冷卻與頻控(必做)
- 同一句/同作者/同模板至少 X 天不重複
-
發送
Push 追加規則(V1.1):若
fallback_level_final > 0或conf_U偏低,需自動「降個性化」:
personalization_power上限降為≤0.5(L1)或0(L2/L3)- 若候選不足,優先回退到「通用安全句庫」,而不是擴大高個性化內容
V1.2(支持问卷跳过)补充:
- 若
profile_answered.need=false或U.need缺失:不得按“need 强命中”召回,候选池应提高通用安全句占比,并至少按 L1 降个性化- 若
profile_answered.emotion=false或U.emotion_score缺失:Push 应偏向Cᵢ.emotion_score为general或 0.4–0.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=1且S_need<1且S_context<1→ 額外扣分 - 若 content 涉及健康敏感(
soft_health_sensitive)→ 扣分(Soft Penalty,不做禁推) - 不確定性懲罰:
P_uncertainty(或併入P_risk),用於在conf_U/conf_C偏低時自動降權高個性化內容
5.5 0–5 次推送的排程策略
-
使用者設定次數 N:
- 第 1 條:need 命中 + 安全
- 第 2 條:emotion 修復
- 第 3 條:self-worth / rest_balance(視 need 而定)
- 第 4–5 條:通用句補位,避免疲勞
六、Widget(每日一句)— Consistency & Brand-first
6.1 目標
- Widget 是「代表你這個 App 的一句話」
- 需要:穩定、可持續、低風險、避免太私密
6.2 流程(每日生成)
- 候選池:以 general + personalization_power≤0.5 為主
- Hard Filter(嚴格)
- Soft Scoring:偏 stage 安全 + emotion 中性/平靜
- 跨日多樣性: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_score在 0.4–0.8(tired→calm)- 避免太低(沉重)
- 避免太高(過嗨)
七、場景差異總結(快速對照)
| 場景 | 目標 | 候選池 | 風險容忍 | 權重重點 | 序列策略 |
|---|---|---|---|---|---|
| Feed | 探索+共鳴 | 大 | 中 | context↑、diversity↑ | MMR 序列 |
| Push | 準+安全 | 小 | 低 | need↑、emotion↑ | 頻控+冷卻 |
| Widget | 穩+代表性 | 中小 | 低 | stage↑、emotion中性 | 跨日多樣性 |
八、(後段解釋預告)提及的算法/概念
- Candidate Generation(混合召回:命中 + 通用 + 探索)
- Hard Filter(規則引擎)
- Linear Weighted Scoring(加權線性模型)
- MMR(Maximal 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 可直接上線的預設參數
- Feed:Top1 命中 + MMR 序列 30 條
- Push:每次 Top1;冷卻 7 天不重複作者,14 天不重複同句
- Widget:emotion_score 限制 0.4–0.8;7 日不重複作者/模板
V1.1 補充(工程預設):
- Feed:MMR
λ=0.7 - Push:啟用
P_uncertainty(或併入P_risk);fallback_level>=1時personalization_power上限降為≤0.5 - Health:
block_health_medical全场景 Hard Filter;soft_health_sensitive走 Soft Penalty
一句話: 同一套 U×Cᵢ 打分,按場景調候選池、權重與重排約束。