feat(report): 形象深度诊断全链路——POST /reports/{id}/full 派生 tier=full 报告,复用 basic 输入与 32 维结果;full 流水线(无视觉阶段)LLM 扩写四大块(十二季定位/规则色板/4场景穿搭/30天计划),三重校验+语义重试+规则兜底降级;删除终身一次硬校验(40920 下线,重复生成由配额兜底);validation 枚举一致性校验放宽(十二季词表);迁移 0003 SSOT 补 full_report 规则行

This commit is contained in:
xsl
2026-09-15 00:02:44 +08:00
parent a1d0171fc5
commit 5c4f1fc75a
16 changed files with 1491 additions and 69 deletions
+10 -4
View File
@@ -15,6 +15,7 @@ path 动态装配。
from __future__ import annotations
import importlib
from collections.abc import Sequence
from typing import Any, Protocol, runtime_checkable
from sqlalchemy.ext.asyncio import AsyncSession
@@ -102,8 +103,12 @@ class StageFailureError(Exception):
super().__init__(f"stage={stage_name} error={type(original).__name__}: {original}")
def assemble_stages(settings: Settings) -> list[Stage]:
"""按 ``settings.report_pipeline_stages`` 的 dotted path 动态装配阶段列表。
def assemble_stages(settings: Settings, *, paths: Sequence[str] | None = None) -> list[Stage]:
"""按阶段配置(dotted path 清单)动态装配阶段列表。
默认读 ``settings.report_pipeline_stages``(basic 报告);tier=full 的
深度诊断由调用方显式传 ``settings.report_full_pipeline_stages``——两条
流水线共用装配与失败语义,只是阶段清单不同。
动态 import 是刻意的插件式装配(见模块 docstring):T16/T17 各自建阶段
模块,不碰本文件;import-linter 看不到这条边,阶段模块自身的依赖仍受
@@ -112,7 +117,8 @@ def assemble_stages(settings: Settings) -> list[Stage]:
模块/类不存在、实例化失败、或不符合 Stage 协议时,收集**全部**缺失项
抛 ``CONFIG_ERROR`` —— 绝不静默跳过:静默等于流水线空跑还扣用户配额。
"""
if not settings.report_pipeline_stages:
stage_paths = list(paths) if paths is not None else list(settings.report_pipeline_stages)
if not stage_paths:
raise AppError(
ErrorCode.CONFIG_ERROR,
message="报告流水线阶段配置为空",
@@ -121,7 +127,7 @@ def assemble_stages(settings: Settings) -> list[Stage]:
missing: list[str] = []
stages: list[Stage] = []
for dotted in settings.report_pipeline_stages:
for dotted in stage_paths:
module_path, sep, attr = dotted.partition(":")
stage: Any = None
if sep and module_path and attr: