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
-18
View File
@@ -11,30 +11,12 @@ from sqlalchemy.ext.asyncio import AsyncSession
from packages.shared.models import RpFeedback, RpInput, RpReport, RpReservation
STATUS_SUCCEEDED = "succeeded"
TIER_BASIC = "basic"
async def get_report(session: AsyncSession, report_id: int) -> RpReport | None:
return await session.get(RpReport, report_id)
async def find_succeeded_basic(session: AsyncSession, *, user_id: int) -> int | None:
"""首次终身资格:该用户是否已有 succeeded 的 basic 报告(需求 §2.1)。
只取 report_id 不取整行——资格判定不需要报告内容。
"""
result = await session.execute(
select(RpReport.report_id)
.where(
RpReport.user_id == user_id,
RpReport.tier == TIER_BASIC,
RpReport.status == STATUS_SUCCEEDED,
)
.limit(1)
)
return result.scalar_one_or_none()
async def list_reports(session: AsyncSession, *, user_id: int, limit: int = 20) -> list[RpReport]:
result = await session.execute(
select(RpReport)