diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1ab0aaf --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "mindfulness", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/spec_kit/User Profile Scoring/spec.md b/spec_kit/User Profile Scoring/spec.md new file mode 100644 index 0000000..4a5a901 --- /dev/null +++ b/spec_kit/User Profile Scoring/spec.md @@ -0,0 +1,190 @@ +# User Profile Scoring(高层规范) + +## 1. 背景与目标 + +本模块用于将 Onboarding 问卷答案转换为标准化、可计算、可版本化的**用户画像(User Profile)**,供其他模块(个性化推荐 / Push 推送排序 / 内容过滤)统一调用。 + +该模块的设计原则: + +- **不做心理诊断**:只描述「此刻允许被如何对待」 +- 区分 **身份(离散)** 与 **状态(连续)** +- 允许「通用」与「高个性化」内容并存,并通过置信度控制“个性化力度” + +来源规则文档:`设计说明文档/客戶端問卷打分規則.md`(V1 / V1.1 工程补充) + +## 2. 模块定位与边界 + +### 2.1 负责(In Scope) + +- 定义**统一画像结构**(字段、类型、取值范围) +- 定义从问卷答案到画像的**映射规则**(V1) +- 生成画像的**元信息**(V1.1:版本、来源、生成时间、置信度) +- 提供最小可复用的“硬规则”输出(用于下游模块做禁推/降风险) + +### 2.2 不负责(Out of Scope) + +- 不负责具体推荐算法实现(相似度计算、排序、探索/利用策略等) +- 不负责内容标签的生成与管理(内容画像 Cᵢ 的维护属于内容/推荐模块) +- 不负责长期行为信号融合(行为修正可在后续版本扩展) + +## 3. 关键概念 + +- **用户画像 U**:由问卷生成,描述用户阶段、状态与当下需求 +- **内容画像 Cᵢ**:内容侧标签/强度(由内容模块维护) +- **置信度 conf_U**:画像可靠程度(用于推送等高风险场景的降个性化/降风险) + +## 4. 输入与输出(对外接口) + +### 4.1 输入(问卷答案) + +V1 假设每题为**单选**: + +- `mom_stage`:`expecting | parenting | unknown` +- `emotion`:`low | overwhelmed | tired | neutral | calm | joyful` +- `context`:`family | work | relationship | friends | health` +- `need`:`emotional_support | parenting_pressure | self_worth | anxiety_relief | rest_balance` + +> 说明:多选 `context/need` 可在后续版本扩展,但 V1 输出结构需保持可兼容升级。 + +### 4.2 输出(用户画像) + +输出为一个 JSON 对象(或等价的 TypeScript 类型),包含: + +- **元信息(V1.1)** + - `profile_version`: string(如 `"v1.1"`) + - `profile_source`: `"questionnaire"`(后续可扩展 `"behavior"` / `"mixed"`) + - `profile_generated_at`: string(ISO8601 时间戳) + - `profile_confidence`: number(0–1) +- **四个维度(V1)** + - `stage`: one-hot + - `emotion_score`: number(0–1) + - `context`: one-hot + - `need`: one-hot + +推荐的最小输出示例(结构示意): + +```json +{ + "profile_version": "v1.1", + "profile_source": "questionnaire", + "profile_generated_at": "2026-01-30T00:00:00Z", + "profile_confidence": 1.0, + "stage": { "expecting": 0, "parenting": 1, "unknown": 0 }, + "emotion_score": 0.4, + "context": { "work": 1 }, + "need": { "rest_balance": 1 } +} +``` + +## 5. 画像字段定义(V1) + +### 5.1 mom_stage(母职阶段,离散) + +映射(one-hot): + +- Pregnant / Preparing → `stage.expecting = 1` +- Parenting → `stage.parenting = 1` +- Prefer not to say → `stage.unknown = 1` + +语义约束: + +- `unknown` 的语义是:**不希望被母职身份定义**(不是“没有孩子”) + +### 5.2 emotion(当下情绪,连续 0–1) + +该分数不是“快乐程度”,而是**可承受刺激与吸收内容的能力**。分数越低越需要减压、陪伴、允许停下;分数越高才适合庆祝、提醒珍惜等高能量调性内容。 + +映射(固定离散值): + +| 选项 | tag | emotion_score | +| --- | --- | --- | +| Low | emotion: low | 0.0 | +| Overwhelmed | emotion: overwhelmed | 0.2 | +| Tired | emotion: tired | 0.4 | +| Okay | emotion: neutral | 0.6 | +| Calm | emotion: calm | 0.8 | +| Joyful | emotion: joyful | 1.0 | + +输出:`emotion_score ∈ [0,1]` + +### 5.3 context(影响来源,离散) + +映射(one-hot): + +- Family → `context.family = 1` +- Work or study → `context.work = 1` +- Relationship → `context.relationship = 1` +- Friends → `context.friends = 1` +- Health → `context.health = 1` + +语义说明: + +- `context` 不是情绪,而是情绪的“触发场景” +- 用于提升内容共感(语境命中),而非硬性过滤 + +### 5.4 need(最需要的支持,离散,推荐权重最高) + +映射(one-hot): + +- Emotional support → `need.emotional_support = 1` +- Parenting pressure → `need.parenting_pressure = 1` +- Self-worth → `need.self_worth = 1` +- Anxiety relief → `need.anxiety_relief = 1` +- Rest & balance → `need.rest_balance = 1` + +语义说明: + +- `need` 是**推荐权重最高的维度** +- 表示“她现在最缺的是哪一种心理资源” + +## 6. 元信息与置信度(V1.1) + +### 6.1 profile_version / source / generated_at + +- `profile_version`:用于规则升级与兼容(建议从 `"v1.1"` 起步) +- `profile_source`:固定为 `"questionnaire"`(后续可扩展) +- `profile_generated_at`:画像生成时间(用于推送降风险) + +### 6.2 profile_confidence(conf_U) + +默认规则(可配置参数): + +- 问卷刚完成:`conf_U = 1.0` +- 随时间衰减(避免用过期状态强个性化推送): + - 0–7 天:`conf_U = 1.0` + - 7–30 天:线性衰减到 `0.7` + - 30 天以上:`conf_U = 0.5`(除非用户重新做问卷或有行为信号更新) + +下游使用建议: + +- Push 推送等高风险场景:当 `conf_U` 低时,应启用不确定性惩罚(例如 `P_uncertainty`)并限制个性化力度上限。 + +## 7. 跨维度硬规则(Hard Rules)输出 + +本模块应向下游暴露“可直接执行”的硬规则结果(例如 `forbidden_tags` 或 `content_tone_blacklist`),以保证在任何排序之前先做安全过滤。 + +V1 核心禁推规则: + +1. **`stage.unknown = 1`** + - 禁推:强指向育儿压力的内容(`need: parenting_pressure`) +2. **`stage.parenting = 1`** + - 禁推:明确怀孕 / 孕期 / 胎动等内容 +3. **`emotion_score ≤ 0.2`(low / overwhelmed)** + - 禁推:高能量庆祝型(joyful 调性)内容 + +原则说明: + +- 这些不是“答案不准”,而是“会造成反感或退出”的高风险匹配,应始终优先执行。 + +## 8. 兼容性与演进策略 + +- **向后兼容**:新版本字段可新增,但不得破坏 V1 的四维度结构与含义 +- **多选扩展**:后续允许 `context/need` 多选时,输出仍可保持 one-hot,但可允许多个 key=1(并提供归一化规则) +- **行为融合**:后续可引入 `profile_source=mixed`,将行为信号用于修正 `emotion_score` 或补全缺失维度,但必须保留 `questionnaire` 原始画像以便可观测与回溯 + +## 9. 验收标准(模块级) + +- Onboarding 填写完成后,能够生成符合本规范的用户画像对象 +- 输出包含元信息(版本、来源、时间、置信度)与四维度字段 +- 硬规则输出可被推荐/推送模块直接用于过滤(先过滤、后打分) + diff --git a/spec_kit/overview.md b/spec_kit/overview.md index cad3471..d6913bf 100644 --- a/spec_kit/overview.md +++ b/spec_kit/overview.md @@ -75,3 +75,14 @@ - 新增 `SheetModal`、`ThemeModal`、`ProfileModal` 并在 Home 中接入 - 新增 `DailyReminderModal` 并从个人主页弹窗打开 - Home:右上角 icon 按钮、主题切换背景、喜欢/讨厌 icon + 动效 + +## User Profile Scoring + +- **目标**:将 Onboarding 问卷答案映射为标准化“用户画像 U”,并输出硬规则与置信度元信息,供推荐/Push 等模块统一复用 +- **核心范围**:mom_stage(离散)、emotion_score(0–1 连续)、context(离散)、need(离散)四维度;以及 `profile_version/source/generated_at/confidence`(V1.1) +- **主要约定**: + - 输出结构稳定可版本化,便于规则演进 + - 置信度随时间衰减,用于推送场景降个性化/降风险 + - 硬规则优先于任何分数计算(例如 `unknown` 禁推育儿压力内容等) +- **阶段产物**: + - `spec_kit/User Profile Scoring/spec.md` diff --git a/设计说明文档/個性化推薦算法規則.md b/设计说明文档/個性化推薦算法規則.md new file mode 100644 index 0000000..21602ee --- /dev/null +++ b/设计说明文档/個性化推薦算法規則.md @@ -0,0 +1,319 @@ +# 正念 APP|三種分發場景推薦算法方案(Feed / Push / Widget · V1) + +> **目標**: +> 針對三種分發方式(Feed、App Push、Widget 每日一句)制定一套一致但可調參的推薦流程。 +> +> **共用基礎**: +> +> * 用戶畫像:U(mom_stage one-hot、emotion_score、context one-hot、need one-hot) +> * 文案畫像: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 的內容 + 一部分通用內容 +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/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_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]` +* `S_context = Cᵢ.context_suitability[U.context]` +* `S_stage`:general=1;命中=1;unknown對非unknown=0.7;其餘=0 +* `S_emotion`:若文案 general→0.8;否則 `1-|U.emotion_score-Cᵢ.emotion_score|` + +個性化加成: +[ +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` +* `U.context.health=1` → 禁推 `block_health_medical`(僅擋「醫療/診斷/嚴重暗示」) + +> `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) + +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` 標籤重合(Jaccard)→ `Sim += 0.1 * Jaccard(tags_c, tags_s)` +* 最終 `Sim` clamp 到 `[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) + +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 > 0` 或 `conf_U` 偏低,需自動「降個性化」: +> +> * `personalization_power` 上限降為 `≤0.5`(L1)或 `0`(L2/L3) +> * 若候選不足,優先回退到「通用安全句庫」,而不是擴大高個性化內容 + +## 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 流程(每日生成) + +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_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:Hard Filter 僅擋 `block_health_medical`;`soft_health_sensitive` 走 Soft Penalty + +> 一句話: +> **同一套 U×Cᵢ 打分,按場景調候選池、權重與重排約束。** diff --git a/设计说明文档/句子文案打分規則.md b/设计说明文档/句子文案打分規則.md new file mode 100644 index 0000000..99e59f9 --- /dev/null +++ b/设计说明文档/句子文案打分規則.md @@ -0,0 +1,255 @@ +# 正念 APP|文案畫像打分標準(Content Profile · Cᵢ · V1) + +> **用途**: +> 本文件定義「每一句文案如何被轉換為可計算的內容畫像(Content Profile)」。 +> 該畫像將與 **用戶畫像 U** 進行匹配,用於個性化推薦與推送排序。 +> +> **使用對象**: +> +> * AI Reviewer(自動打分) +> * 人工內容審稿/校準 +> * 推薦系統(selector / ranker) + +--- + +## 一、核心原則(請務必遵守) + +1. **不是評價文案好不好**,而是: + + > 這句話「適合對誰說、在什麼狀態下說」 + +2. **能不標就不標**: + + * 沒有明確指向,就標為 `general` + * 不要為了打分而硬塞標籤 + +3. **高個性化 = 高風險**: + + * 指向越具體(孕吐、育兒比較、婆媳),越需要搭配禁推規則 + +--- + +## 二、Content Profile 結構總覽 + +每一句文案 Cᵢ,需產出以下欄位: + +```text +C_i.stage // general / expecting / parenting / unknown +C_i.emotion_score // 0–1 或 general +C_i.context_suitability // 各 context 的 {0, 0.5, 1} +C_i.need_suitability // 各 need 的 {0, 0.5, 1} +C_i.personalization_power // 0 / 0.5 / 1 +C_i.risk_flags // 風險標記(可多個;Hard Filter / Soft Penalty 會使用) + +// Rerank / 去重 / 頻控所需(若資料源可提供,強烈建議補齊) +C_i.content_id // 句子唯一 ID(建議 stable,不隨文案微調而變) +C_i.author_id // 作者/來源 ID(可為空) +C_i.template_id // 模板 ID(可為空;用於多樣性與頻控) + +// 置信度(可選;用於 Push 的「不確定性懲罰 / 降個性化」) +C_i.review_confidence // 0–1;AI/人工對標註結果的置信度(缺省可按流程給預設值) +``` + +--- + +## 三、mom_stage(母職階段)定位規則 + +### 可選值 + +* `general`(預設) +* `expecting` +* `parenting` +* `unknown` + +### 判斷標準 + +#### `expecting` + +**必須出現以下任一類語義**: + +* 懷孕、孕期、孕吐、胎動、產檢、待產 +* 明確指向「即將成為媽媽」的心理狀態 + +> 若只是提到「未來」「新階段」,不算 expecting + +--- + +#### `parenting` + +**必須出現以下任一類語義**: + +* 已有孩子的日常(哄睡、尿布、育兒、學校、教養) +* 明確「身為媽媽正在照顧孩子」 + +--- + +#### `unknown` + +**僅在以下情況使用**: + +* 文案明確「不論你在哪個階段」「不管你是否是媽媽」 +* 明確避免母職角色語言 + +--- + +#### `general` + +* 沒有任何明確母職階段指向(**最常見**) + +--- + +## 四、emotion_score(情緒調性)— 連續型 + +### 對齊用戶 emotion 軸 + +| 調性 | emotion_score | +| --------- | ------------- | +| 安撫低落 / 陪伴 | 0.0–0.2 | +| 減壓、縮小世界 | 0.2–0.4 | +| 疲累修復 | 0.4 | +| 中性穩定 | 0.6 | +| 平靜、呼吸 | 0.8 | +| 慶祝、喜悅 | 1.0 | + +### 打分規則 + +* 若文案同時包含多種調性,取**主導語氣** +* 若無明確情緒調性 → 設為 `general` + +--- + +## 五、context_suitability(影響來源適配) + +### 可選 context + +* family / work / relationship / friends / health + +### 打分方式(對每一個 context) + +| 分數 | 含義 | +| --- | -------- | +| 1.0 | 明確命中該情境 | +| 0.5 | 通用可推 | +| 0.0 | 不適合/可能刺痛 | + +### 示例 + +* 提到「老公/婆婆/孩子」→ family = 1 +* 提到「上班/職場拉扯」→ work = 1 +* 完全抽象支持 → 所有 context = 0.5 + +--- + +## 六、need_suitability(支持需求適配)— **最重要** + +### 可選 need + +* emotional_support +* parenting_pressure +* self_worth +* anxiety_relief +* rest_balance + +### 打分方式(對每一個 need) + +| 分數 | 含義 | +| --- | ---------- | +| 1.0 | 明確回應此 need | +| 0.5 | 部分相關/通用支持 | +| 0.0 | 無關或反向 | + +### 判斷原則(舉例) + +* 「你不需要撐著,我在」→ emotional_support = 1 +* 「你已經做得夠好了」→ self_worth = 1 +* 「慢一點、休息一下」→ rest_balance = 1 +* 「不是你做錯,只是育兒真的很難」→ parenting_pressure = 1 + +--- + +## 七、personalization_power(個性化力度) + +> 用於控制「專屬程度 vs 風險」 + +| 值 | 定義 | +| --- | ------------ | +| 0.0 | 完全通用(任何人都可推) | +| 0.5 | 弱指向(稍微貼近某情境) | +| 1.0 | 強指向(高度具體) | + +### 判斷依據 + +* 是否提及具體角色/場景/困境 +* 是否假設用戶正在經歷某件事 + +--- + +## 八、risk_flags(禁推規則標記) + +> 用於 **Hard Filter**,優先於任何分數 + +### 重要語義(工程側必讀) + +1. `risk_flags` **描述的是「這句話對哪些用戶/狀態不安全」或「需要降權」**,而不是內容的 `stage`。 +2. **命名規範(工程側定死)**:一律使用 `unsafe_for_*` / `block_*` / `soft_*` 前綴。 + - `unsafe_for_*`:對特定用戶狀態不安全,通常進 Hard Filter(場景不同可調) + - `block_*`:高風險健康/醫療等,進 Hard Filter(特別是 Push) + - `soft_*`:不做硬性過濾,但在排序中做風險懲罰(Soft Penalty) +3. 若不確定,寧可標更保守的 flag(Push 安全優先)。 + +### 標準 flags(V1.1,推薦使用) + +* `unsafe_for_stage_unknown` + + * 文案假設用戶正在育兒 / 有孩子 / 以「你作為媽媽」為前提(對 `mom_stage=unknown` 容易冒犯) + +* `unsafe_for_stage_parenting` + + * 文案明確懷孕語境(對 `mom_stage=parenting` 可能刺痛) + +* `unsafe_for_emotion_low` + + * 高昂慶祝型、過嗨、強刺激(對 `emotion_score ≤ 0.2` 不適合) + +* `block_health_medical`(Hard Block) + + * 具「醫療/診斷/嚴重暗示」:疾病確診、用藥、治療方案、醫囑、手術、急重症、危險警示等 + * 這類內容在 **Health 情境** 下特別容易翻車,建議 Hard Filter + +* `soft_health_sensitive`(Soft Penalty) + + * 健康/身心照顧相關,但不含診斷/治療/嚴重暗示:疲憊、睡眠、壓力、呼吸、覺察身體、日常照護 + * 不做禁推,但在 Push/Widget 需降權,避免過度私密或觸發 + +### 舊 flags(V1,已棄用但需兼容) + +> 若歷史資料仍使用舊 flag,工程側需在入庫/讀取時做一次映射,避免語義漂移。 + +* `block_stage_unknown` → `unsafe_for_stage_unknown` +* `block_stage_parenting` → `unsafe_for_stage_parenting` +* `block_emotion_low` → `unsafe_for_emotion_low` +* `block_health_sensitive` → `block_health_medical` 或 `soft_health_sensitive` + + * 判斷原則:含診斷/治療/嚴重暗示 → `block_health_medical`;否則 → `soft_health_sensitive` + +> AI Reviewer 若不確定,寧可標記 flag + +--- + +## 九、AI Reviewer 打分流程(強烈建議) + +1. **先判斷是否 general**(能 general 就 general) +2. 再標註:stage(若有) +3. 再決定 emotion_score(主導語氣) +4. 再填 context / need suitability +5. 最後判斷 personalization_power +6. 若有任何「可能翻車」風險 → 加 risk_flag + +--- + +## 十、設計總結(一句話) + +> Content Profile 的目的不是把話分門別類, +> 而是避免在錯的時間,用錯的方式,對錯的人說話。 + +本文件為 V1,可隨實際推送數據進行校準與升級。 diff --git a/设计说明文档/客戶端問卷打分規則.md b/设计说明文档/客戶端問卷打分規則.md new file mode 100644 index 0000000..d40480f --- /dev/null +++ b/设计说明文档/客戶端問卷打分規則.md @@ -0,0 +1,221 @@ +# 正念 APP|用戶畫像打分標準(User Profile Scoring Spec · V1) + +> **用途**: +> 本文件定義「問卷完成後,如何將答案轉換為可計算的用戶畫像(User Profile)」; +> 該畫像將用於後續的 **個性化內容推薦 / 推送排序**。 +> +> **設計原則**: +> +> * 不做心理診斷,只描述「此刻允許被如何對待」 +> * 區分 **身份(離散)** 與 **狀態(連續)** +> * 允許「通用」與「高個性化」內容並存 + +--- + +## 一、整體結構概覽 + +問卷完成後,系統需生成一個用戶畫像 **U**,包含四個維度: + +1. **mom_stage**(母職階段|離散型) +2. **emotion**(當下情緒|連續型) +3. **context**(影響來源|離散型) +4. **need**(當下最需要的支持|離散型) + +該畫像將與內容畫像 **Cᵢ** 進行匹配,計算推薦分數。 + +### V1.1 工程補充欄位(用於不確定性控制/可觀測) + +> 目的:在 Push 等高風險場景,當用戶畫像可能過期或不可靠時,自動「降個性化 / 降風險」。 + +建議在 U 中補充以下元資訊(不影響原有四維度打分): + +* `profile_version`:如 `"v1.1"` +* `profile_source`:`questionnaire`(後續可擴展 `behavior` / `mixed`) +* `profile_generated_at`:ISO8601 時間戳 +* `profile_confidence`(= `conf_U`):`0–1` + +`profile_confidence` 建議規則(V1.1 默認,可調參): + +* 問卷剛完成:`conf_U = 1.0` +* 隨時間衰減(避免用過期狀態強個性化推送): + * 0–7 天:`conf_U = 1.0` + * 7–30 天:線性衰減到 `0.7` + * 30 天以上:`conf_U = 0.5`(除非用戶重新做問卷或有行為信號更新) + +> Push 推送時若 `conf_U` 偏低,推薦系統需啟用 `P_uncertainty` 並限制 `personalization_power` 上限(見「個性化推薦算法規則」V1.1)。 + +--- + +## 二、mom_stage(母職階段)— 離散型 + +### 問卷題目 + +**Which stage of motherhood are you in?** + +選項與對應標籤: + +* Pregnant / Preparing → `mom_stage: expecting` +* Parenting → `mom_stage: parenting` +* Prefer not to say → `mom_stage: unknown` + +### 打分方式(One-Hot) + +| 欄位 | 值 | +| ----------------- | ----- | +| U.stage.expecting | 1 或 0 | +| U.stage.parenting | 1 或 0 | +| U.stage.unknown | 1 或 0 | + +> **說明**: +> +> * `mom_stage` 是「身份 / 階段」,不是強度,不做連續軸線 +> * `unknown` 的語義是:**不希望被母職身份定義**(不是「沒有孩子」) + +### 推送原則(高層) + +* `unknown`:避免任何「你應該怎麼當媽媽」的內容 +* `expecting`:避免「已經有孩子」的育兒細節 +* `parenting`:可接受具體育兒壓力、現實困境相關內容 + +--- + +## 三、emotion(當下情緒)— 連續型(0–1) + +### 問卷題目 + +**How are you feeling right now?** + +### 映射為數值軸(能量/情緒穩定度) + +| 選項 | tag | emotion_score | +| ----------- | -------------------- | ------------- | +| Low | emotion: low | 0.0 | +| Overwhelmed | emotion: overwhelmed | 0.2 | +| Tired | emotion: tired | 0.4 | +| Okay | emotion: neutral | 0.6 | +| Calm | emotion: calm | 0.8 | +| Joyful | emotion: joyful | 1.0 | + +生成:`U.emotion_score ∈ [0,1]` + +### 語義說明 + +* 這不是「快樂程度」,而是 **可承受刺激與吸收內容的能力** +* 分數越低,內容越需要「減壓、陪伴、允許停下」 +* 分數越高,才適合「慶祝、提醒珍惜」 + +--- + +## 四、context(影響來源)— 離散型 + +### 問卷題目 + +**What’s been influencing how you feel?** + +| 選項 | tag | +| ------------- | --------------------- | +| Family | context: family | +| Work or study | context: work | +| Relationship | context: relationship | +| Friends | context: friends | +| Health | context: health | + +### 打分方式(One-Hot) + +| 欄位 | 值 | +| ----------------------------------------------------- | ----- | +| U.ctx.family / work / relationship / friends / health | 1 或 0 | + +### 語義說明 + +* context **不是情緒**,而是情緒的「觸發場景」 +* 用於提升內容共感(語境命中),而非硬性過濾 + +--- + +## 五、need(最需要的支持)— 離散型(最關鍵) + +### 問卷題目 + +**What kind of support do you need most right now?** + +| 選項 | tag | +| ------------------ | ------------------------ | +| Emotional support | need: emotional_support | +| Parenting pressure | need: parenting_pressure | +| Self-worth | need: self_worth | +| Anxiety relief | need: anxiety_relief | +| Rest & balance | need: rest_balance | + +### 打分方式(One-Hot) + +| 欄位 | 值 | +| ------------------------------------------------------------------------------------------ | ----- | +| U.need.emotional_support / parenting_pressure / self_worth / anxiety_relief / rest_balance | 1 或 0 | + +### 語義說明 + +* `need` 是 **推薦權重最高的維度** +* 表示「她現在最缺的是哪一種心理資源」 + +--- + +## 六、跨維度約束(Hard Rules) + +以下規則在推薦時 **優先於任何分數計算**: + +### 核心禁推規則(V1) + +1. **mom_stage = unknown** + + * ❌ 禁推:`need: parenting_pressure`(強指向) + +2. **mom_stage = parenting** + + * ❌ 禁推:明確懷孕 / 孕期 / 胎動等內容 + +3. **emotion_score ≤ 0.2(low / overwhelmed)** + + * ❌ 禁推:高能量慶祝型(joyful 調性)內容 + +> 原則: +> +> * 這些不是「不準」,而是「會造成反感或退出」 + +--- + +## 七、用戶畫像最終輸出結構(示例) + +```json +{ + "profile_version": "v1.1", + "profile_source": "questionnaire", + "profile_generated_at": "2026-01-30T00:00:00Z", + "profile_confidence": 1.0, + "stage": { + "expecting": 0, + "parenting": 1, + "unknown": 0 + }, + "emotion_score": 0.4, + "context": { + "work": 1 + }, + "need": { + "rest_balance": 1 + } +} +``` + +--- + +## 八、設計總結(給產品/工程/AI Reviewer) + +* **mom_stage / context / need**:描述「你現在允許我用什麼身份、從哪個角度對你說話」 +* **emotion_score**:描述「你現在能承受多強的刺激與建議」 +* 推薦的本質不是猜你是誰,而是 **避免用錯語氣對你說話** + +> 本文件為 V1,後續可疊加: +> +> * 多選 context / need +> * 行為信號(點擊、收藏)對 emotion 的動態修正