Files
mindfulness/spec_kit/Personalized Reco/modules/rerank-freqcap/tasks.md
2026-02-02 16:47:37 +08:00

173 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Rerank & Freqcap重排 / 去重 / 频控Tasks
> 对应计划:`spec_kit/Personalized Reco/modules/rerank-freqcap/plan.md`
>
> 本清单执行原则:
>
> - 本模块只做 **Dedup / Freqcap / Feed MMR 重排**,不做 Soft Scoring 与 Hard Filter。
> - V1 冷却窗口以“输入集合代表窗口内历史”为准(后续接入服务端历史再按天计算)。
---
## 0. 任务标记规则
- 用勾选框标记执行状态:
- `[ ]` 未开始
- `[x]` 已完成
- 每个任务都要求可独立验收(有明确产出/可运行的检查方式)。
---
## 1. 文档对齐(先把口径写死,避免实现漂移)
- [x] 1.1 校对 `modules/rerank-freqcap/spec.md``modules/rerank-freqcap/plan.md` 一致性
- **检查点**
- 输入:`scene/scored_candidates/history/k/config` 字段与命名一致
- 输出:`ranked_items``meta` 字段集合一致
- 去重键:`sentence_key=content_id``author_key``template_key` 口径一致
- FeedMMR λ=0.7 与 Sim 规则一致
- **验收**两份文档不存在冲突描述且“V1 冷却窗口语义”写清楚(集合代表窗口内历史)。
- [x] 1.2 在 `plan.md` 中补充/固定“标签构造策略”与“候选截断策略”(若后续要改再更新)
- **变更点**
- 明确 `tags` 的 V1 定义:`stage + need_argmax + context_argmax`
- 明确 `top_n_for_mmr` 默认值与作用(性能兜底)
- **验收**:实现时不会出现“标签到底取哪些 key”的二义性。
---
## 2. 目录与骨架(与推荐子模块同级)
- [x] 2.1 新建目录 `server/app/features/personalized_reco/rerank_freqcap/`
- **包含**
- `__init__.py`
- `types.py``ScoredCandidate``RerankConfig``RerankMeta``RerankResult`
- `defaults.py`(按 scene 的默认参数λ、cooldown_*、top_n_for_mmr
- `utils.py`ID 归一化、Jaccard、tag 构造等)
- `rerank.py`(主入口 `rerank_and_freqcap`
- **验收**:可通过 `app.features.personalized_reco.rerank_freqcap.*` 正常 import。
---
## 3. 类型与接口(稳定契约,便于 reco-engine 调用)
- [x] 3.1 定义 `ScoredCandidate`(最小字段集合)
- **必须字段**
- `content_id: int`
- `final_score: float`
- **建议字段**(用于多样性/频控):
- `author_id: str | None`
- `template_id: str | None`
- `content_profile`(至少能取到 stage/need_suitability/context_suitability缺失时需降级
- **验收**:能承载 MMR 相似度计算所需数据;缺失字段不会导致异常。
- [x] 3.2 定义 `RerankConfig`(可调参)
- **字段**
- Feed`mmr_lambda`(默认 0.7)、`top_n_for_mmr`(默认 200
- Push/Widget`cooldown_sentence_days/cooldown_author_days/cooldown_template_days`(用于配置与可观测)
- **验收**:能从 scene 推导默认 config或由调用方传入覆盖
- [x] 3.3 定义 `RerankMeta``RerankResult`
- **meta 必须字段**
- `candidate_pool_size_after_dedup`
- `candidate_pool_size_after_freqcap`
- `missing_history_fields`
- **建议字段**
- `freqcap_filtered_counts`sentence/author/template
- **验收**:字段集合固定;任何输入都能产出 meta包括候选为空
---
## 4. 核心算法实现V1 最小集合)
- [x] 4.1 实现历史 ID 归一化(避免 str/int 混用漏过滤)
- **规则**
- `already_recommended_ids` / `touched_or_viewed_ids` 尽量转为 `int` 集合
- 转换失败的值忽略并记录 debug
- **验收**:单测覆盖 `["1", 2, "bad"]` 等混合输入,过滤结果正确且稳定。
- [x] 4.2 实现 Dedup必做
- **规则**:过滤 `content_id ∈ seen_ids` 的候选
- **产出**`meta.candidate_pool_size_after_dedup`
- **验收**:输出不包含历史出现过的 `content_id`
- [x] 4.3 实现 FreqcapPush/Widget 必做Feed 可选)
- **V1 策略**
- 句子维度(必做):同句硬过滤(使用 dedup 的 seen_ids 即可)
- 作者/模板维度(增强项):
- 若提供 `recent_author_ids`:命中则硬过滤;否则在 `missing_history_fields` 记录 `author`
- 若提供 `recent_template_ids`:命中则硬过滤;否则在 `missing_history_fields` 记录 `template`
- **产出**
- `candidate_pool_size_after_freqcap`
- `freqcap_filtered_counts`(建议)
- **验收**:在有/无 `recent_*_ids` 输入时行为一致且可解释。
- [x] 4.4 实现 Feedtag 构造与相似度 `Sim`
- **tag 规则V1 写死)**
- `stage:<stage>`
- `need:<argmax_key>`(从 `need_suitability` 取最大值 key为空则跳过
- `context:<argmax_key>`(从 `context_suitability` 取最大值 key为空则跳过
- **Jaccard**`|A∩B|/|AB|`,空集合时返回 0
- **Sim 累加规则**
- 同 content_id → 1
- template_id 相同且非空 → +0.6
- author_id 相同且非空 → +0.3
- +0.1 * Jaccard(tags)
- clamp 到 `[0,1]`
- **验收**:单测覆盖缺失字段(无 author/template/tags时仍能算出稳定 Sim。
- [x] 4.5 实现 FeedMMR 选序列
- **规则**
- Top1`final_score` 最大
- 后续:按 `MMR(c)=λ*Rel(c)-(1-λ)*maxSim` 选择
- `Rel=final_score`
- **性能兜底**:先截断候选到 `top_n_for_mmr` 再做 MMR
- **验收**
- Top1 恒等于最高分
- 候选足够时,序列不出现大量同作者/同模板紧邻重复(可用阈值断言)
- [x] 4.6 实现 Push/Widget最终 TopK
- **规则**dedup+freqcap 后按 `final_score` 降序取前 k 条
- **验收**:输出长度 ≤ k且分数单调不增允许相等
- [x] 4.7 实现主入口 `rerank_and_freqcap(...) -> RerankResult`
- **规则**
- 三场景共用 dedup
- FeedMMRPush/WidgetTopK
- 必须输出 meta即使 ranked_items 为空)
- **验收**:任何输入(含空候选)不抛异常,并输出稳定结构。
---
## 5. 单元测试pytest纯函数为主
- [x] 5.1 新建测试文件 `server/tests/test_rerank_freqcap.py`
- **用例覆盖**
- dedup历史集合过滤正确含 str/int 混用)
- freqcap有/无 recent_author/template 的分支与 meta 缺失标记
- feed mmrTop1=最高分;后续避免同作者/模板紧邻(构造数据断言)
- push/widgetTopK 输出正确
- **验收**`pytest -q tests/test_rerank_freqcap.py` 通过。
---
## 6. 最终自检清单(合入前)
- [x] 6.1 文档一致性检查
- **验收**`spec.md` / `plan.md` / 实现接口签名三者一致(尤其 meta 字段与默认参数)。
- [x] 6.2 回归检查(不影响已实施模块)
- **验收**:不修改 `content-repository``scoring` 的既有逻辑;仅新增 `rerank-freqcap` 模块与测试。
- [x] 6.3 全量测试通过
- **命令**(在 `server/`
- `pytest -q`
- **验收**:所有用例通过。
- [x] 6.4 全部完成后更新大规范 `overview.md`
- **变更点**
-`modules/rerank-freqcap/` 标记为“已实施”
- 增加一条变更记录(日期 + 交付物plan/tasks/代码/测试)
- **验收**`spec_kit/Personalized Reco/overview.md` 中模块状态与交付记录准确。