Files
meida/docs/开发任务包/T16-报告诊断装配.md

92 lines
7.7 KiB
Markdown
Raw Permalink 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.
# T16 · 报告流水线·视觉分析与 32 维诊断装配(mock vision)
> 对应任务:`T-P3-01`(各项返回置信度与质量标记)、`T-P3-06` 🔴(**32 维度**每维四要素完整,缺失显式标注)| 分支:`task/t16-report-diagnosis` | worktree:`/home/xsl/meida_backend-t16`
> 先读《README.md(协作规程)》,遵守全部纪律。**第四批拼流水线:T15 定 Stage 接口(协调提交的 pipeline 骨架),你供视觉与诊断两个阶段,文件名与类名已由 T15 的任务契约定死——按下面 §2 的 dotted path 精确落位。**
## 2. 你要创建的文件(与流水线的挂点,禁差分毫)
| 文件 | 导出 | 挂进流水线的名字 |
| --- | --- | --- |
| `packages/report/dimensions.py` | `DIMENSIONS`(32 项冻结结构)等 | —(纯字典) |
| `packages/report/vision.py` | `VisionProvider` Protocol、`DeterministicVisionProvider`、`build_vision_provider(settings)` | —(被 vision_stage 用) |
| `packages/report/vision_stage.py` | `class VisionStage` | `packages.report.vision_stage:VisionStage` |
| `packages/report/diagnosis_stage.py` | `class DiagnosisStage` | `packages.report.diagnosis_stage:DiagnosisStage` |
Stage 接口以协调提交的 `packages/report/pipeline.py` 骨架 docstring 为准(`name` + `async run(ctx)`;`ctx.report.result[stage.name]` 写产物;`ctx.rp_input.derived_features` 是你的中间态位)。
## 3. 维度字典(dimensions.py——本任务的事实核心)
**必读**:`G:\meida\docs\美学报告-需求文档.md` 的 **§4 诊断维度字典**(32 行表)。逐行编码成:
```python
@dataclass(frozen=True, slots=True)
class DimensionSpec:
number: int # 1~32(33/34 已永久废弃,不复用)
key: str # 稳定英文键,如 body_shape / season_code / face_shape
name_cn: str
source: str # questionnaire | vision | color | kb | rule | llm(按表「数据来源」列归类)
basic_coverage: str # "full" | "label" | "partial" | "none"(按「初级」列的 ✅/标签/部分/❌)
```
- `DIMENSIONS: tuple[DimensionSpec, ...]` 必须恰好 32 项、number 1~32 连续;模块常量 `BASIC_FULL_KEYS`(初级 full 覆盖集,验收「初级 21/32」口径的机器可读形态——**以你逐行统计为准并写注释**)。
- key 命名参考 kb/记忆系统已有词汇(body_shape、face_shape、season_code…),全库一致。
## 4. 视觉分析(vision.py + vision_stage.py)
1. **`VisionProvider` Protocol**:`async def analyze(photo_meta: dict, questionnaire: dict) -> dict`(返回派生特征 dict:体型、脸型、肤色 Lab 采样、量感/直曲粗判……**形状由你定,写进 docstring**——这是 T9 SPIKE 之后的正式接口位,真实 RTMPose/BiRefNet 实现后续替换)。
2. **`DeterministicVisionProvider`**:不读照片字节(V1 骨架根本没有照片下载步骤),从 `questionnaire` + `photo_meta["object_key"]` 的 sha256 派生**确定性**特征(同输入同输出——黄金集与集成测试才能断言)。特征生成规则写注释:哪个问题驱动哪个维度、哈希驱动哪些枚举选择。
3. `build_vision_provider(settings)`:按 `settings.report_vision_provider` 选择(当前只认 `"deterministic"`,其它 → `AppError(CONFIG_ERROR)`)。
4. **`VisionStage`**(name=`"vision"`):`ctx.rp_input.derived_features` **已存在且非空 → 跳过**(写 `ctx.report.result["vision"] = {"skipped": true, "reused": true}`——这就是 T-P3-09 的实现点);否则 provider.analyze → 写 `derived_features` 并 flush → `result["vision"] = {"status": "ok", "dimensions_touched": [...]}`。质量标记:photo_meta 里可选 `quality_flags`(模糊/背光等,mock 下默认空列表)透传进产物(T-P3-01 的形状)。
## 5. 诊断装配(diagnosis_stage.py)
`DiagnosisStage`(name=`"diagnosis"`):
1. 输入 = questionnaire(`ctx.rp_input.questionnaire`)+ derived_features;**逐个维度**产四要素(T-P3-06 验收原文):
```python
@dataclass(frozen=True, slots=True)
class DimensionResult:
number: int
key: str
value: Any # 结论值(枚举/数值/列表)
confidence: float # 0~1:问卷自评 0.6、确定性视觉 0.85、规则推导 0.9(口径写注释,对齐记忆系统 §3.5)
source: str # questionnaire | vision | rule | derived
evidence: str # 一句人话依据(将出现在报告里)
rule_hits: list[str] # 命中的 rule_key
status: str # "ok" | "skipped"——**缺失/输入不足的维度必须显式 skipped + 原因,不允许缺键**(验收红线)
```
2. 数据流:问卷字段直接映射(性别/身高体重/职业/生日/核心诉求/场景权重/心理风格/偏好禁忌…);视觉字段映射(体型/脸型/肤色档位/季型/量感/直曲/基因风格…);**规则引擎联动**:构造 `RuleContext`(body_shape/face_shape/features/goals…)→ `RulesService` 载入 published 规则 → `evaluate()` → verdict 的 recommend/avoid 聚合进「核心诉求/偏好与禁忌」相关维度的 rule_hits 与 evidence。规则服务接口以 `packages/rules/service.py` 实际代码为准。
3. 产物:`ctx.report.result["diagnosis"] = {"dimensions": [32 个 DimensionResult 的 dict], "coverage": {"basic_full": N, "total": 32}}`;序列化用 dataclass `asdict`。
4. **色板维度(#19/21)**:V1 骨架从 `kb_color` 读该季型 base/accent/avoid 各取若干(库空则该维度 skipped+「色板未录入」——**显式缺失优于编造**,这正是 skipped 语义的用例)。
## 6. 测试要求
- 单测 `tests/unit/test_report_dimensions.py`:32 项、number 连续、33/34 不存在、basic_coverage 枚举合法、`BASIC_FULL_KEYS` 与逐行统计一致。
- 单测 `tests/unit/test_report_vision.py`:确定性(同输入同输出)、不同问卷驱动不同体型、工厂未知名拒绝。
- 单测 `tests/unit/test_report_diagnosis.py`:四要素齐全性——**构造故意缺问卷+缺视觉的场景,断言缺失维度 status=skipped 且 32 键全在**;规则命中进 rule_hits(用内置最小规则集,不连库——RulesService 若需 DB,把规则求值抽成可注入纯函数 `evaluate_dimensions(ctx_data, verdict)`)。
- 集成 `tests/integration/test_report_stages.py`(新文件,**只测你的两个阶段,不测整条流水线**——T15 的集成已覆盖编排):建 rp_report/rp_input + 种 2 条 published 规则 → VisionStage → DiagnosisStage 断言 derived_features 落库、32 维全键、规则 rule_hits 出现、kb_color 为空时色板维度 skipped。
## 7. 禁改清单
通用禁改之外:`packages/report/` 除你四个文件外全部(pipeline/service/repo/schemas 归 T15,copy*/validation* 归 T17)、`apps/**`、全部已有测试。
## 8. 验收标准(T-P3-01/06)
1. `DIMENSIONS` 与需求文档 §4 逐行一致(32 项、编号连续、初级覆盖口径机器可读);
2. 32 维四要素全量输出,缺失显式 skipped——**任何输入组合下 result["diagnosis"]["dimensions"] 恒 32 键**(单测证明);
3. 视觉中间态复用:derived_features 存在时 vision 阶段 skipped/reused;
4. 规则引擎硬结论进入 rule_hits/evidence;
5. 全部检查绿(mypy 范围同 T15 + 你的文件;`packages/report` 整包进列表)。
## 9. 提交信息
```
feat(report): deterministic vision provider and 32-dimension diagnosis assembly
dimensions.py 逐行编码需求文档 §4(32 项四要素、缺失显式 skipped)+
VisionProvider 接口位与确定性实现 + 规则引擎联动 rule_hits(T-P3-01/06)。
偏差说明:<如有写在这里,无则写"无">
```