# 子模块:Reco Engine(推荐引擎编排)|Spec ## 1. 目标描述 实现推荐的主编排器(Orchestrator): - 输入用户画像 + 历史集合 + 场景参数。 - 调用 `Content Repository` 拉取候选。 - 执行统一 Pipeline:Candidate → Hard Filter → Soft Scoring → Rerank/Freqcap → Fallback Ladder。 - 输出推荐句子与 `meta`(可观测字段),供 API 或 Celery 上层直接下发。 --- ## 2. 输入 / 输出定义 ### 2.1 输入 - `scene`: `feed | push | widget` - `user_profile`: 客户端问卷画像(V1.2) - `already_recommended_ids`: `List[str|int]` - `touched_or_viewed_ids`: `List[str|int]` - `k`: int(feed 默认 30;push/widget 默认 1) - `now`: 时间戳 - (可选)`constraints`:黑名单 author/template、最大候选量上限等 ### 2.2 输出 - `items: List[RecommendedItem]`(长度 ≤ k) - `content_id`、`text`、`final_score` - `fallback_level_final` - `explanations`(可选,便于调参/排查) - `meta: RecoMeta` - `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 必填) - `missing_fields`(need/context/emotion 的缺失情况) - `scene`、`conf_U` --- ## 3. 缺失字段判定(必须与客户端契约一致) - `U.need` 为空对象 `{}` 或不存在 → 视为缺失 - `U.context` 为空对象 `{}` 或不存在 → 视为缺失 - `U.emotion_score` 为 `null`/不存在 → 视为缺失 当缺失明显或 `conf_U` 偏低时: - Push:必须启用不确定性惩罚 `P_uncertainty`,并自动降个性化(限制 `personalization_power` 上限)。 - 任意场景:候选生成至少按 **L1** 处理(降个性化,增加通用安全占比)。 --- ## 4. Fallback Ladder(回退梯度,必须实现) - L0:正常召回配比 - L1:放宽匹配 + `personalization_power ≤ 0.5` - L2:回退通用池 + `personalization_power = 0` - L3:仅安全池(白名单/安全池) 触发条件(任一满足即可回退): - 候选池为空 / Hard Filter 清空 / 去重清空 / 频控清空 - served_k < k(feed 可允许部分不足,但需记录并可继续回退补齐,具体由实现配置) 每次回退必须更新 meta 中的候选规模与触发原因。 --- ## 5. 验收标准(可验证) - **稳定性**:任意输入(包括画像字段缺失、历史集合为空/很大)不报错,返回结构稳定。 - **回退可观测**:当候选不足时能逐级回退,且 `fallback_level_final` 与 `empty_reason` 正确。 - **去重生效**:输出不包含 `already_recommended_ids` 与 `touched_or_viewed_ids` 中的 content_id。 - **风险优先**:Hard Filter 始终优先执行(尤其 `block_health_medical` 必挡)。 - **跨调用复用**:同一引擎既可被 FastAPI API 调用,也可被 Celery 任务调用(无框架耦合)。