Files
mindfulness/spec_kit/Personalized Reco/modules/content-repository/spec.md
2026-02-02 11:22:35 +08:00

103 lines
5.1 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.
# 子模块Content Repository候选查询与数据访问层Spec
## 1. 目标描述
提供推荐算法可注入的、与 ORM/SQL 解耦的数据访问接口:
- 按场景与用户画像拉取候选内容画像Cᵢ
-`content_id` 批量获取内容画像(去重/重排/补字段)。
- 对 risk_flags、suitability JSON 等“存储形态”做统一解析与兼容(对上提供稳定结构)。
> 规则口径risk_flags 命名与语义严格按 `句子文案打分规则`;若历史数据存在旧 flag需在读取层做一次映射避免语义漂移
>
> 存储形态对齐 `modules/db-design/plan.md`:读取层需要将 `contents` + `content_profiles` + `content_risk_flags` 组装为上层稳定的 `ContentProfile` 结构。
---
## 2. 输入 / 输出定义
### 2.1 输入
- `scene`: `feed | push | widget`
- `user_profile`: 客户端问卷画像V1.2;字段允许缺失)
- `fallback_level`: `0|1|2|3`
- `limit`: 候选条数上限(由引擎配置)
- (可选)排除集合:`exclude_content_ids`(用于 DB 层先排一部分,减少传输;类型为 `List[int]`,与 MySQL 自增 `content_id` 对齐)
- 数据库会话/连接(实现层使用 `AsyncSession` 注入)
### 2.2 输出
- `List[ContentProfile]`(稳定字段契约):
- `content_id``int`MySQL 自增主键)
- `text`:文案文本
- `stage``general | expecting | parenting | unknown`
- `emotion_score``float | None`(约定:`None` 表示 general
- `context_suitability``Dict[str, float]`(见 4.1 的 key 集合;值为 `0/0.5/1`
- `need_suitability``Dict[str, float]`(见 4.1 的 key 集合;值为 `0/0.5/1`
- `personalization_power``float`(对上稳定口径为 `0/0.5/1`;若 DB 存 `0/5/10`,读取层需映射)
- `risk_flags``List[str]`(已做旧→新映射、去重;命名只允许 `unsafe_for_* / block_* / soft_*`
- 可选:`author_id``template_id``review_confidence`
### 2.3 数据存储形态(对齐 DB 设计)
> 对齐:`spec_kit/Personalized Reco/modules/db-design/plan.md`
- `contents`:提供 `content_id``text`、(可选)`author_id``template_id`
- `content_profiles`:提供 `stage``emotion_score``context_suitability_json``need_suitability_json``personalization_power`(推荐存 `0/5/10`)、(可选)`review_confidence`
- `content_risk_flags`:通过关联表提供风险标记集合(同一 content 下按 `uniq_content_flag(content_id, flag)` 去重)
---
## 3. 接口(建议)
推荐模块对该子模块只依赖抽象接口Python Protocol/ABC 均可):
- `fetch_candidates(scene, user_profile, fallback_level, limit, exclude_content_ids=None) -> List[ContentProfile]`
- `fetch_contents_by_ids(content_ids: List[int]) -> List[ContentProfile]`
---
## 4. 关键规则与实现约束
### 4.1 字段缺失与默认值
-`review_confidence` 缺失:输出时默认按 `0.7`(对齐 `句子文案打分规则` V1.2 约定)。
- `context_suitability/need_suitability` 若缺失:**读取层必须补齐为“全 0.5 的通用可推”结构**(稳定输出,避免上层分支判断)。
- `context_suitability` 必须包含 5 个 key`family/work/relationship/friends/health`
- `need_suitability` 必须包含 5 个 key`emotional_support/parenting_pressure/self_worth/anxiety_relief/rest_balance`
- 补齐时上述 key 的默认值均为 `0.5`
- `personalization_power`:若 DB 采用 `0/5/10` 存储,读取层必须映射为 `0.0/0.5/1.0` 对上输出。
### 4.2 risk_flags 兼容映射(若存在历史旧数据)
对齐 `句子文案打分规则` 的旧→新映射:
- `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`
输出约束:
- 输出的 flags 必须已去重,且不得包含任何旧命名。
### 4.3 性能约束
- 不得产生 N+1 查询:候选与字段必须一次或少量批量查询获取。
- `fetch_candidates` 必须支持 limit并在 DB 层尽量过滤(减少应用层扫描)。
- `fetch_contents_by_ids` / `fetch_candidates` 推荐查询形态:
- `contents` JOIN `content_profiles`,再 LEFT JOIN `content_risk_flags`(或先批量取 profiles再批量取 flags 并在应用层聚合),避免按 `content_id` 循环查 flags。
---
## 5. 验收标准(可验证)
- `fetch_contents_by_ids`
- 输入任意 `content_id` 列表,返回包含完整字段的 `ContentProfile` 列表(无重复、可缺省字段按约定兜底)。
- `fetch_candidates`
- 在不同 `scene``fallback_level` 下能返回候选(即便画像缺失也不报错)。
- risk_flags 映射正确:输出的 flag 名称集合只包含新命名(`unsafe_for_* / block_* / soft_*`)。
- 性能:
- 单次调用不出现按 content_id 循环查库的行为(可通过日志/测试断言查询次数)。