Files
meida/docs/技术架构文档.md
xslandCursor 2934954eb2 按交叉评审对齐文档与代码口径,并挡住 reference 下的密钥文件
表名、配额种子和字段名以产品方案与架构为准;文档仓库补 .gitignore,避免 git add -A 把 API Key 推进远端。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 11:28:35 +08:00

86 KiB
Raw Permalink Blame History

「美搭」技术架构文档

版本:v1.4 | 更新日期:2026-08-14 | 状态:待技术评审

本文的定位:把产品需求翻译成可直接拆解为开发任务的技术方案。读完这份文档,应该能回答三个问题——系统由哪些部分组成、数据长什么样、每条关键链路怎么跑通。

前置阅读:《技术选型与调研报告》(所有选型结论与理由,本文只引用编号 TD-xx,不重复论证) 配套阅读:《需求规格说明》(需求编号 FR-xx/NFR-xx)、《合规与安全方案》、《开发任务拆解》


1. 架构目标与约束

1.1 这个系统真正难的地方

在动手设计之前先明确难点,否则很容易把它当成一个「CRUD + 调几个 AI 接口」的普通应用,那会在三个月后付出代价:

  1. 它是一个「长耗时任务为主」的系统,不是请求-响应系统。报告生成、换装出图都在数十秒量级。这意味着任务中心、状态机、幂等、进度反馈、失败退款、断线恢复不是附加功能,而是主干链路。
  2. AI 输出必须被约束,而不是被信任。报告结论与搭配建议要可解释、可审计、不能违反禁忌规则。因此架构上必须有「检索 → 规则约束 → 生成 → 生成后校验」的闭环,而不是把用户问题直接丢给大模型。
  3. 它处理的是敏感个人信息(人脸),且产出的全部是 AI 生成内容。合规不是上线前补的文档,而是架构约束:原图不落盘、生成物统一打标识、输入输出双向审核。
  4. 成本随活跃度线性增长。GPU 出图与大模型调用都是按量付费。如果没有从第一天就把成本埋进链路并可归因到功能和用户,用户量上来后无法优化,只能凭感觉砍功能。
  5. 知识库是持续演进的资产,它的更新频率远高于代码。所以规则、色板、单品必须是数据而不是代码,且有配套的运营入口与回归测试。

1.2 质量属性优先级

按项目当前阶段(V1 单端、效果优先、团队 4~6 人)排序:

优先级 质量属性 具体要求
1 正确性与可解释性 建议不违反硬性禁忌;每条结论可追溯到规则或知识条目
2 合规性 人脸处理、AI 标识、内容审核、备案登记均满足现行要求
3 可演进性 域边界清晰,V2 拆服务/换模型/多端时不需要重写
4 可观测性 业务漏斗、AI 成本、任务健康三张看板齐备
5 性能 见 NFR 指标;报告与出图允许秒级到分钟级,但等待体验必须做好
6 极致成本优化 V1 只要求「可归因、可预警」,不要求「最省」

1.3 架构约束(不可协商)

约束 来源
客户端为鸿蒙原生 ArkTS,服务端保持端无关 TD-01
服务端全 Python(FastAPI) 项目决策
基础设施以腾讯云为主,服务器部署在中国大陆 项目决策 + TD-15 手机号获取要求
人脸原图不进入持久化存储 TD-20
所有对外生成物必须经过统一合规出口 TD-21
V1 不接入任何支付能力,配额为唯一成本控制手段 TD-28
V2 起虚拟商品支付必须走华为 IAP TD-16
V1 不上微服务、不上 K8s、不上专用向量库与图数据库 TD-08/TD-09,团队规模

2. 系统上下文

                                  ┌──────────────────────┐
                                  │   鸿蒙客户端 (ArkTS)  │
                                  └──────────┬───────────┘
                                             │ HTTPS / SSE
                                             ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                        美搭服务端 (Python / 腾讯云)                        │
│                                                                          │
│   API 层 ──▶ 业务域模块 ──▶ AI 能力层 ──▶ 数据层                          │
│                    │                                                     │
│                    └──▶ 任务队列 ──▶ Worker                              │
└───┬──────────┬──────────┬──────────┬──────────┬──────────┬───────────────┘
    │          │          │          │          │          │
    ▼          ▼          ▼          ▼          ▼          ▼
┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐┌──────────────┐
│华为服务 ││大模型   ││腾讯云AI ││自有换装 ││腾讯云   ││腾讯云   ││腾讯云基础设施 │
│账号/推送││DeepSeek││人脸识别 ││发型服务 ││天御审核 ││短信SMS ││COS/CDN/PG/  │
│Push    ││智谱GLM ││        ││(GPU)   ││        ││        ││Redis/CLS     │
└────────┘└────────┘└────────┘└────────┘└────────┘└────────┘└──────────────┘

注:V1 不接入天气 API(TD-33),Agent 的天气类问题走「反问用户 + 城市月份推断气候区」降级

外部依赖及其失效影响(每一个都要有降级方案,见 §13.4):

外部系统 用途 失效影响 降级策略
华为 Account Kit 登录(通道一) 该通道不可用 手机号验证码登录仍可用(两条通道不得互相依赖);游客模式可继续体验
腾讯云短信 SMS 登录(通道二,TD-32) 该通道不可用 华为账号登录仍可用;登录页给出明确提示而非笼统报错
华为 Push Kit 任务完成通知 通知不到 应用内任务中心轮询兜底
DeepSeek / GLM 文案生成、对话 报告与对话不可用 双供应商自动切换;均失败时报告排队重试,对话返回兜底话术
腾讯云人脸识别 面部分析 报告无法生成面部维度 报告降级为「体型+色彩」子集,标注待补全
自有换装服务 出图 换装不可用 任务转排队,不扣配额,超时退还
腾讯云天御 内容审核 不可降级 审核失败一律按「拦截」处理(fail-close),宁可少发不可漏审
华为 IAP 支付(V2 起) 无法购买 提示稍后再试,不影响已有权益。V1 不依赖此项

🔑 登录必须有两条互不依赖的通道,这是 V1 唯一的单点故障防护。华为账号是唯一通道时,华为侧授权异常会让用户直接进不来产品;而一键登录已推至 V2(TD-29),所以手机号验证码是 V1 的必需项,不是可选项。


3. 总体架构

3.1 分层视图

┌───────────────────────────────────────────────────────────────────────┐
│ L1 客户端层                                                            │
│  鸿蒙 ArkTS:页面 / 状态管理 / 端侧缓存 / 图片压缩 / SSE流式渲染          │
└───────────────────────────────────────────────────────────────────────┘
                                  ▼
┌───────────────────────────────────────────────────────────────────────┐
│ L2 接入层                                                              │
│  CLB + Nginx:TLS / 限流 / 防刷 / 请求日志 / 静态与图片走 CDN            │
└───────────────────────────────────────────────────────────────────────┘
                                  ▼
┌───────────────────────────────────────────────────────────────────────┐
│ L3 API 层(FastAPI,面向端的编排层)                                     │
│  认证鉴权 · 参数校验 · 幂等 · 配额校验与预扣 · 统一响应 · OpenAPI          │
└───────────────────────────────────────────────────────────────────────┘
                                  ▼
┌───────────────────────────────────────────────────────────────────────┐
│ L4 业务域层(模块化单体:包内隔离,禁止跨域直接访问对方数据表)             │
│ ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┐      │
│ │identity│profile │ report │ agent  │ tryon  │   kb   │billing │      │
│ │账号会话│画像记忆│美学报告│对话Agent│换装发型│ 知识库 │配额计量│      │
│ ├────────┼────────┼────────┼────────┼────────┴────────┴────────┤      │
│ │  task  │wardrobe│compliance│ notify │                        │      │
│ │任务中心│ 衣橱V2 │合规出口 │ 通知   │                        │      │
│ └────────┴────────┴─────────┴────────┴────────────────────────┘      │
└───────────────────────────────────────────────────────────────────────┘
                                  ▼
┌───────────────────────────────────────────────────────────────────────┐
│ L5 AI 能力层(可独立部署与扩容,对上以内部 API 暴露)                     │
│ ┌──────────────┬──────────────┬──────────────┬──────────────┐        │
│ │ llm-gateway  │  vision-svc  │retrieval-svc │ rules-engine │        │
│ │多模型路由    │分割/关键点/  │混合检索+重排 │决策表求值+   │        │
│ │Prompt版本    │色值采样/体型 │              │可解释路径    │        │
│ ├──────────────┼──────────────┼──────────────┴──────────────┤        │
│ │ matting-svc  │  tryon-svc   │                             │        │
│ │批量抠图      │换装/发型(GPU)│                             │        │
│ └──────────────┴──────────────┴─────────────────────────────┘        │
└───────────────────────────────────────────────────────────────────────┘
                                  ▼
┌───────────────────────────────────────────────────────────────────────┐
│ L6 数据层                                                              │
│  PostgreSQL + pgvector(业务/知识库/向量/事件)· Redis(缓存/队列/限流) │
│  COS 四桶(临时/用户内容/知识素材/报告产物)· CLS(日志与审计)           │
└───────────────────────────────────────────────────────────────────────┘

                      ┌──────────────────────────────┐
       横向贯穿:      │ Celery Workers(gpu/cpu/io/beat)│
                      │ 可观测性(OTel/Prom/Grafana)    │
                      │ 配置与密钥(SSM/KMS)            │
                      └──────────────────────────────┘

3.2 为什么是「模块化单体 + 独立 AI 服务」

这是本架构最关键的一个取舍,理由:

业务域做单体:identity/profile/report/agent/billing 之间事务关联紧密(一次报告生成要扣配额、写画像、写记忆、记成本)。拆成微服务后这些操作就需要分布式事务或最终一致性补偿,对 4~6 人团队是净损失。单进程内一个数据库事务就解决了。

AI 能力做独立服务:它们的资源画像与业务代码完全不同——GPU 依赖、模型文件体积、推理并发模型、扩缩容节奏都不一样。混在一个进程里会导致「换装排队把 API 拖慢」。独立部署后可以单独限流、单独扩容、单独重启。

但单体不等于混乱。硬性规则:

  1. 每个域是一个 Python 包,只能通过对方暴露的 service 接口调用,禁止直接查对方的表。
  2. 领域逻辑放在 packages/domain,不依赖 FastAPI、不依赖数据库会话,可纯单元测试。
  3. 跨域的写操作通过域内事件(进程内事件总线 + 持久化 outbox)解耦,例如「报告完成」事件被 profile(写画像)、memory(写记忆)、notify(推送)、billing(结算成本)分别消费。
  4. 数据库虽是单库,但表按域前缀命名,为将来拆库预留边界。

演进触发条件:当某个域的写入 QPS 或数据量成为瓶颈,或需要独立发布节奏时,按 §19 的路径拆出。不要提前拆。


4. 模块职责与依赖

4.1 业务域模块清单

模块 职责 关键对外能力 不负责
identity 账号、登录、会话、设备、游客迁移、同意授权记录 login() get_current_user() merge_guest() record_consent() 权益判定(归 billing)
profile 用户画像(诊断结论)+ 分层记忆系统 get_profile() get_memory_snapshot() write_memory() resolve_conflict() 报告生成流程
report 报告触发判定、生成编排、版本管理、分享 can_trigger() create_report() get_report() create_share() 具体的视觉分析与文案生成(调 AI 层)
agent 会话管理、意图识别、上下文组装、生成编排 chat_stream() extract_preference() 知识检索实现(调 retrieval)
tryon 换装/发型的业务编排、素材校验、结果管理 create_tryon_task() get_result() GPU 推理(调 tryon-svc)
kb 知识实体/关系/规则/素材的读写与发布 query_entities() get_rules() publish() 检索算法(调 retrieval)
billing V1:配额账本、流水、周期重置、任务奖励发放。V2 增:会员、订单、IAP 校验 check_quota() reserve() commit() refund() grant() 定价策略配置(配置化);V1 无支付相关职责
task 统一任务中心:创建、状态机、进度、查询、取消 submit() get_status() list_user_tasks() 具体任务实现(Worker)
compliance 统一合规出口:审核、水印、元数据标识、内容编号登记、审计 moderate() publish_asset() register_content() 业务判断
notify 推送、应用内消息、Token 管理 push() notify_task_done() —
wardrobe 我的衣橱(V2) — —

域与包不是一一对应。 上表按产品职责切(profile 含记忆);§16.1 的 packages/ 按发布与依赖切。记忆有独立表、独立生命周期,且会被 agent / report 同时写入,因此代码上是独立的 packages/memory,产品职责仍归 profile 域。跨域只许 import memory 的 service,不许直接读 pf_memory。

4.2 依赖规则

identity ← 所有模块(读当前用户)
billing  ← report / tryon / agent(消耗资源前预扣)
task     ← report / tryon(长耗时任务统一走它)
compliance ← report / tryon / agent / kb(所有产物出口)
profile  ← report(写入)/ agent(读取+写入)
kb       ← agent / report(读取)

禁止的依赖:compliance 不得反向依赖任何业务域(它必须能被任何模块安全调用);identity 不得依赖其他业务域(避免登录链路被业务拖累)。

4.3 AI 能力层服务

服务 形态 内容 资源
llm-gateway 进程内包(V1)→ 独立服务(V2) 多供应商路由、Prompt 版本、结构化输出约束、流式、缓存前缀优化、成本计量、限流降级 IO 密集
vision-svc 独立服务 人像分割(云)、人体关键点(ONNX 自建)、色值采样、体型测算、人脸属性与关键点(云) CPU(含 ONNX)
retrieval-svc 进程内包 混合检索:硬过滤 → 规则命中 → 向量召回 → BM25 → 重排 → 解释路径 CPU + PG
rules-engine 进程内包 决策表求值、硬约束校验、命中链输出 CPU
matting-svc 离线批处理 BiRefNet 抠图 + 白底标准化 + 规格校验 GPU(按需)
tryon-svc 独立服务(现有服务改造) 换装三工作流、发型更换/发色 GPU(常驻或按需)

llm-gateway 为何 V1 先做进程内包:它没有独立的资源诉求(纯 IO),拆成服务只增加一跳网络。但它的接口必须按远程调用来设计(无共享内存假设、明确超时、可序列化的入参出参),这样 V2 拆出去时零成本。

4.4 现有换装服务的改造要求

既然服务自有可控(TD-00 前提),必须做以下改造,否则它会成为整个系统的不稳定源:

改造项 现状问题 要求
鉴权 可能是开放接口 改为内部服务,仅允许内网/网关调用,带服务间令牌
调用模式 同步长连接 改为提交任务 + 回调通知(或提供任务查询接口),避免长连接占用
幂等 无 接受 idempotency_key,重复提交返回同一结果
并发控制 无 明确最大并发数并对外暴露,让上游队列按容量限流
成本埋点 无 每次推理返回 gpu_seconds 与模型版本,供成本归因
结果存储 直传阿里云 OSS 改为写入腾讯云 COS(统一存储与生命周期治理);历史数据做迁移或双读
输入校验 未知 前置校验图片规格、人脸存在性、单品白底图规格,尽早失败
版本管理 未知 模型/工作流版本号随结果返回,便于回溯效果变化

5. 技术栈总览

层次 选型 决策依据
客户端 HarmonyOS ArkTS + ArkUI TD-01
端侧能力 Account Kit / Push Kit(V1);IAP Kit / Core Speech Kit(V2) TD-15~TD-17、TD-14、TD-28
接入 腾讯云 CLB + Nginx + CDN TD-03
服务端 Python 3.12 + FastAPI + Uvicorn/Gunicorn TD-02
ORM/迁移 SQLAlchemy 2.0 (async) + Alembic TD-02
校验 Pydantic v2(同时用于 LLM 结构化输出约束) TD-02
任务 Celery + Redis(gpu/cpu/io/beat 四队列) TD-11
数据库 PostgreSQL 16 + pgvector TD-08
缓存 Redis 7 —
存储 腾讯云 COS(4 桶)+ CDN TD-03
大模型 DeepSeek(主)+ 智谱 GLM(备/视觉) TD-04
Embedding BGE-M3(自建 ONNX) TD-22
视觉 腾讯云人脸识别 + RTMPose(ONNX) + BiRefNet TD-05~TD-07
审核 腾讯云天御 IMS/TMS TD-13
渲染 Playwright + Chromium(服务端长图/PDF) TD-12
可观测 OpenTelemetry + Prometheus + Grafana + CLS TD-24
部署 Docker + Docker Compose(V1)→ TKE(V2) TD-03
CI/CD GitHub Actions 或腾讯云 CODING;ruff + mypy + pytest 卡关 TD-02

6. 数据模型

6.1 设计原则

  1. 单库多域,表名以域前缀区分(id_/pf_/rp_/kb_/ag_/tr_/bl_/tk_/cp_)。
  2. 主键统一用雪花 ID(bigint),不用自增(避免枚举攻击与将来分库冲突),不用 UUID 作主键(索引局部性差)。对外暴露的 ID 做混淆编码。
  3. 不存人脸原图,不存可反推生物特征的数据。诊断结果只存分类标签与色值等派生量(TD-20)。
  4. 所有涉及配额/金额的表都有幂等键与流水,任何余额变更必须有对应流水记录,余额可由流水重算校验。V1 虽不涉及金钱,此原则同等适用 —— 用户对"次数被白扣"的敏感度不比扣钱低。
  5. 软删除 + 硬删除双轨:常规软删除;账号注销走硬删除任务(合规要求,见《合规与安全方案》)。
  6. JSONB 用于「结构会演进但不需要索引全部字段」的场景(诊断结论、规则条件、检索轨迹);需要过滤的字段一律提升为列。

6.2 核心表清单

identity 域

表 关键字段 说明
id_user user_id PK, status('active'/'frozen'/'deleting'/'deleted'), nickname, avatar_key, register_source, created_at, last_active_at, deleted_at 内部主键,与外部身份解耦。手机号不存本表,见下行
id_user_identity user_id, provider('huawei'/'phone'), union_id, open_id, phone_enc(AES 加密), phone_hash(检索用), UNIQUE(provider,union_id) 一个用户可有多个外部身份。手机号作为一种 provider 存在本表,不在 id_user 冗余 —— 它是登录凭证而非用户属性,且便于统一加密与脱敏(NFR-SEC-03)。检索用 phone_hash,展示用解密后掩码
id_guest guest_id, device_fp, merged_to_user_id, created_at 游客数据,登录后合并
id_device device_id, user_id, push_token, os_version, last_seen_at 推送 Token 管理
id_consent consent_id, user_id, consent_type, granted bool, doc_version, granted_at, revoked_at, client_ip, ua 合规留证:人脸的单独同意必须独立成行。枚举见下表
id_session session_id, user_id, refresh_token_hash, expire_at, revoked 刷新令牌服务端可撤销

profile 域(画像与记忆)

表 关键字段 说明
pf_profile profile_id, user_id, label, is_default 预留多档案(帮家人诊断的场景),V1 只创建默认档案
pf_diagnosis diagnosis_id, profile_id, source_report_id, dimensions JSONB, version, overall_confidence, created_at 32 个诊断维度的结构化结论(字典见美学报告 §4,为唯一事实源;编号 33/34 已随 TD-31 移除且不再复用);按版本追加,不覆盖
pf_memory memory_id, user_id, layer(L0~L5), mem_key, mem_value JSONB, confidence numeric, status, source, evidence_ref, valid_from, last_reinforced_at, decay_after, created_at 记忆项主表;索引 (user_id,layer,status)。status 与 source 的枚举取值以《用户系统与记忆系统-需求文档》§3.3 为唯一事实源,见下表
pf_memory_event event_id, memory_id, action('create'/'reinforce'/'decay'/'conflict'/'user_edit'/'delete'), detail JSONB, created_at 记忆变更审计,支撑「我的记忆」页面的可解释性
pf_memory_snapshot user_id, snapshot JSONB, token_count, content_hash, built_at, expire_at 注入 LLM 的画像摘要缓存,避免每轮重算

枚举取值(本轮对齐,此前架构与用户系统文档给了两套不兼容的枚举)

⚠️ 原架构表写 status=archived/rejected、source=explicit/implicit/report/behavior,与用户系统 §3.3 的枚举无法对应。以用户系统文档为准,因为它的取值承载了衰减与冲突消解的语义(decayed/overridden 必须可区分,否则 §3.6 的冲突消解无法实现)。

字段 取值 语义要点
pf_memory.status active / pending_confirm / decayed / overridden / deleted decayed(置信度衰减至 < 0.3,可恢复)与 overridden(被新证据覆盖)必须区分,前者可由用户恢复,后者不可
pf_memory.source explicit_user_input / user_setting / report_vision / self_reported / behavior_inferred / llm_extracted 衰减规则只作用于 behavior_inferred 与 llm_extracted(用户系统 §3.5),因此不能合并为笼统的 implicit
id_consent.consent_type privacy(隐私政策)/ face(人脸,须独立成行)/ personalization(个性化推荐)/ push(推送通知)/ minor(未成年人确认) ⚠️ personalization 不可省略:用户系统 §3.10 要求记忆写入必须建立在该项授权之上,缺了它记忆系统就没有合规依据

report 域

表 关键字段 说明
rp_report report_id, user_id, profile_id, tier('basic'/'full'), status, version, result JSONB, model_info JSONB, content_code, rendered_asset_key, cost_cents, created_at, completed_at content_code 为 AI 标识内容编号(TD-21)
rp_input input_id, report_id, questionnaire JSONB, photo_meta JSONB, derived_features JSONB 只存派生特征与图片元信息,不存原图
rp_share share_id, report_id, share_token, expire_at, view_count, revoked 分享链接可失效、可撤回

kb 域(知识库)

表 关键字段 说明
kb_entity entity_id, entity_type(12 类), name, attrs JSONB, status('draft'/'reviewing'/'published'/'archived'), version, source, license, updated_by 12 类实体统一表 + attrs 差异化
kb_relation from_id, rel_type, to_id, weight, confidence, evidence 邻接表,递归 CTE 做多跳(TD-09)
kb_rule rule_id, version, status, priority, conditions JSONB, effects JSONB, is_hard, evidence, author, reviewer, published_at 决策表(TD-10)
kb_chunk chunk_id, entity_id, chunk_type, text, embedding vector(1024), embedding_model, embedding_version, tsv tsvector 向量 + 全文双索引,支撑混合检索
kb_asset asset_id, entity_id, asset_type, cos_key, spec_check JSONB, tryon_ready bool, review_status, license tryon_ready 是换装闭环的关键标志位
kb_color color_id, season_code, role('base'/'accent'/'avoid'), lab_l,lab_a,lab_b, hex, name_cn 自建色板(TD-18)
kb_gap gap_id, query_text, filter_ctx JSONB, hit_count, first_seen_at 知识缺口埋点:无检索结果的查询,驱动内容生产

agent 域

表 关键字段 说明
ag_conversation conv_id, user_id, title, rolling_summary, status, msg_count, created_at 长会话滚动摘要存这里(L4 记忆)
ag_message msg_id, conv_id, role, content, intent, retrieval_trace JSONB, rule_hits JSONB, model, tokens_in/out/cached, cost_cents, moderation JSONB, created_at retrieval_trace + rule_hits 让每个回答可复盘
ag_feedback feedback_id, msg_id, rating, reason, created_at 驱动隐式偏好推断与质量评估

tryon 域

表 关键字段 说明
tr_task task_id, user_id, workflow_type, input_refs JSONB, result_asset_key, gpu_seconds, model_version, content_code, cost_cents 与统一任务中心 tk_task 一对一关联
tr_favorite fav_id, user_id, asset_key, tags, created_at 用户收藏的效果图

task 域(统一任务中心)

表 关键字段 说明
tk_task task_id, user_id, task_type('report'/'tryon'/'hairstyle'/'matting'/'render'), status, progress, stage_text, idempotency_key UNIQUE, payload JSONB, error_code, retry_count, quota_reserved, submitted_at, started_at, finished_at, eta_seconds 全系统唯一的长耗时任务视图,前端任务中心直接读它。⚠️ 字段名由 points_reserved 改为 quota_reserved —— V1 是配额不是点数,用 points 命名会在实现期误导

billing 域(V1 为配额与计量,无支付)

V1 不接支付(TD-28)。本域在 V1 的职责是配额限制与计量。关键设计:表结构一次做到位,V2 上支付时不需要迁移。

表 关键字段 V1 说明
bl_quota user_id, quota_key, period_key, used, limit_value, bonus_granted, updated_at;UNIQUE(user_id,quota_key,period_key) ✅ V1 扣减判定的唯一依据。周期配额计量(日/月/终身),按 period_key 自然重置,不要写定时清零任务。limit_value 是本周期创建时从规则拷下的 base_limit 快照(规则中途被改,本周期仍按快照判定);bonus_granted 物化本周期已获任务奖励,避免每次判定都聚合流水
bl_quota_rule quota_key, period_type, base_limit, task_bonus_max, hard_cap ✅ 配额规则配置化(FR-BILL-04),改配置不发版。数值与 quota_key 映射见下表,一律引用产品方案 §3.2,禁止在种子里另写一套
bl_ledger tx_id, user_id, delta, tx_type, status, reason, ref_type, ref_id, balance_after, idempotency_key UNIQUE, created_at ✅ 流水是真相,但不参与 V1 的判定(判定看 bl_quota)。tx_type V1 用 system_grant/consume/refund 三种,V2 增加 purchase/gift —— 这是 V1→V2 免迁移的关键
bl_wallet user_id PK, balance, version(乐观锁) ✅ ⚠️ V1 仅用于「跨周期不清零」的额度(如首次终身报告);周期类额度一律走 bl_quota。V2 语义扩展为点数余额,同一张表,不改结构

bl_quota_rule.quota_key 与产品方案 §3.2 的对应(种子必须与此表一致):

quota_key 对应 §3.2 行 period_type base / task_bonus_max / hard_cap
agent_chat AI 对话 day 10 / 10 / 40
tryon 换装试穿 day 3 / 3 / 8
hairstyle 发型 / 发色试戴 day 3 / 2 / 6
hd_export 高清导出 day 1 / 0 / 3
report_basic 初级美学报告(首次) lifetime 1 / 0 / 1
report_regen 报告重新生成 month 1 / 1 / 2

「每日 ≤ 2」在月额度上限为 2 时自然满足,不必再拆一条日配额。记忆条数 200 是存储上限,不是消耗型配额,不进本表。 游客额度按设备维度计量,依赖 id_guest;游客合并链路未建之前不写入 guest_* key,避免种子里出现没人读的第二套口径。

🔑 四张表的职责边界见 §7.4 开头。这是最容易实现成"两套并行扣减逻辑"的地方,务必先读那一段。 | bl_membership | user_id, level, valid_from, valid_to, source_order_id, auto_renew | ❌ V2 | 会员 | | bl_order | order_id, user_id, product_id, product_type, price_cents, platform('huawei_iap'), purchase_token UNIQUE, status, verified_at, raw_receipt JSONB | ❌ V2 | purchase_token 唯一约束防重复发货(TD-16) |

原 bl_point_tx 改名为 bl_ledger:V1 阶段它记录的是配额流水而非点数流水,用 point 命名会在 V1 造成误解。改用中性名称,同时新增 tx_type 字段承载两个阶段的语义差异。

compliance 域

表 关键字段 说明
cp_content_registry content_code PK(27 位), content_type, ref_type, ref_id, provider_code, model_info JSONB, generated_at AI 生成内容编号登记(TD-21)
cp_moderation_log log_id, target_type, target_id, provider, suggestion, labels JSONB, action, created_at 审核留证
cp_audit_log audit_id, actor_type, actor_id, action, target, before JSONB, after JSONB, ip, created_at 后台操作审计,知识库改动必须留痕
cp_data_request request_id, user_id, type('export'/'delete'), status, completed_at 个人信息导出/删除请求(法定权利)

观测与成本

表 关键字段 说明
ob_ai_call call_id, user_id, scene, provider, model, prompt_id, prompt_version, tokens_in/out/cached, tokens_reasoning, latency_ms, cost_cents, rate_tier, success, error_code, ref_type, ref_id, created_at 成本归因的唯一数据源,按月分区。prompt_id/prompt_version 使每次调用可复现(§8.1 要求 Prompt 版本化,缺这两列就无法回答「上周的报告是哪版 Prompt 生成的」);tokens_reasoning 单独记思考模式 token(按输出价计费,混进 tokens_out 会掩盖开关思考模式的成本差异);rate_tier 记录该次调用适用的峰谷档位,否则事后无法复核 cost_cents。保留口径:明细至少保留到 V2 定价完成(T-P6-16);满 12 个月的分区可迁冷存储,不可按常规日志周期删除 —— 删了就失去定价依据
ob_event event_id, user_id, event_name, props JSONB, client_ts, server_ts 埋点事件,按月分区(TD-23)

6.3 诊断维度的存储形态

32 个诊断维度(字典见《美学报告-需求文档》§4,为唯一事实源)用 pf_diagnosis.dimensions JSONB 存储,但每个维度都是结构化三元组,不是自由文本:

{
  "color_season": {
    "value": "浅暖柔和型",
    "confidence": 0.82,
    "evidence": ["skin_lab:[68.2,12.4,18.7]", "hair_lab:[24.1,6.2,9.8]", "contrast:low"],
    "source": "vision+rule",
    "rule_hits": ["R-COLOR-0021", "R-COLOR-0034"]
  },
  "body_shape": {
    "value": "X型",
    "confidence": 0.76,
    "evidence": ["shoulder_hip_ratio:1.02", "waist_hip_ratio:0.71"],
    "source": "vision+rule",
    "rule_hits": ["R-BODY-0007"]
  }
}

为什么必须带 confidence 和 evidence:低置信度维度要在报告中降级表述(「你的体型偏向 X 型」而不是断言),并且要能在用户质疑时说明依据。这也是记忆系统冲突消解的输入——用户显式反馈会覆盖低置信度的机器推断。


7. 关键链路设计

7.1 美学报告生成(最复杂的链路)

客户端                    API              task/Worker           AI 能力层
  │                        │                    │                    │
  │ 1.POST /reports        │                    │                    │
  │   (idempotency_key)    │                    │                    │
  ├───────────────────────▶│                    │                    │
  │                        │ 2.触发资格校验      │                    │
  │                        │  (已有报告?配额?)   │                    │
  │                        │ 3.配额预扣(reserve) │                    │
  │                        │ 4.创建 tk_task     │                    │
  │◀── task_id ────────────┤                    │                    │
  │                        │ 5.入队(cpu队列)     │                    │
  │                        ├───────────────────▶│                    │
  │ 6.订阅进度(轮询/Push)   │                    │ 7.拉取临时区原图     │
  │                        │                    ├───────────────────▶│
  │                        │                    │ 8.内容审核(图片)     │
  │                        │                    │ 9.人像分割           │
  │                        │                    │ 10.人体关键点(ONNX) │
  │                        │                    │ 11.人脸关键点+属性   │
  │                        │                    │ 12.色值采样(Lab)     │
  │                        │                    │ 13.体型/季型/脸型测算│
  │                        │                    │◀── 结构化诊断 ──────┤
  │                        │                    │ 14.**立即删除原图**  │
  │                        │                    │ 15.规则引擎求值      │
  │                        │                    │   (建议/禁忌/依据)   │
  │                        │                    │ 16.知识库检索        │
  │                        │                    │   (配色/单品/发型)   │
  │                        │                    │ 17.LLM 生成文案      │
  │                        │                    │   (结构化输出约束)   │
  │                        │                    │ 18.生成后校验        │
  │                        │                    │   (禁忌违反=0?色值在板内?)│
  │                        │                    │ 19.文本审核          │
  │                        │                    │ 20.渲染长图(Playwright)│
  │                        │                    │ 21.合规出口:         │
  │                        │                    │   水印+元数据+编号登记│
  │                        │                    │ 22.写画像/记忆/成本   │
  │                        │                    │ 23.配额 commit      │
  │                        │                    │ 24.Push 通知        │
  │◀──── 报告就绪 ─────────┴────────────────────┤                    │

关键工程要求:

要求 做法
原图生命周期 上传直传 COS 临时桶(预签名 URL,不经过应用服务器);Worker 拉取后处理,第 14 步显式删除;桶级 2 小时生命周期作为兜底
失败即退款 任何步骤失败,tk_task 转 failed 并触发 refund();用户看到明确原因与「重试」入口
分步可恢复 第 7~13 步的视觉分析结果落库为中间态,LLM 或渲染失败时不需要重跑视觉分析(也就不需要用户重新上传)
生成后校验不可跳过 校验失败最多重试 2 次(提高约束强度),仍失败则降级为「规则直出模板文案」,绝不放行违规内容
等待体验 阶段文案随进度更新;预估时间基于历史 p50;超过阈值转为「后台生成 + 完成推送」,允许用户离开页面
幂等 相同 idempotency_key 重复提交返回同一 task_id,不重复扣减配额

7.2 Agent 对话(含检索与画像注入)

用户提问
   │
   ▼
① 输入审核(TMS + 备案关键词库)───拦截──▶ 返回安全提示,记录日志
   │ 通过
   ▼
② 意图识别(轻量模型 / 规则前置)
   ├─ 场景咨询 / 单品搭配 / 风格建议 / 闲聊 / 越界(医疗、身材评判等)
   ▼
③ 上下文组装(token 预算严格分配)
   ├─ 系统提示词(固定前缀,放最前以命中缓存)
   ├─ 画像摘要(L0/L1/L2,来自 pf_memory_snapshot)
   ├─ 会话滚动摘要(L4)
   └─ 检索结果(见 ④)
   ▼
④ 混合检索(retrieval-svc)
   ├─ a. 硬过滤:SQL WHERE(季型/体型禁忌/场合/季节)
   ├─ b. 规则命中:rules-engine 求值,取建议与禁忌
   ├─ c. 向量召回:pgvector 相似度 Top-K
   ├─ d. 关键词召回:tsvector BM25
   ├─ e. 融合重排:RRF + 规则权重 + 新鲜度
   └─ f. 输出:知识片段 + 命中规则 ID + 图谱路径(供解释链)
   ▼
⑤ LLM 生成(llm-gateway,流式 SSE)
   └─ 约束:只能使用检索到的知识;硬禁忌不得出现;输出结构化搭配卡片
   ▼
⑥ 生成后校验:禁忌违反检查 + 色值在色板内检查
   ▼
⑦ 输出审核(TMS)───拦截──▶ 重新生成或返回兜底
   ▼
⑧ 落库:message + retrieval_trace + rule_hits + 成本
   ▼
⑨ 异步:偏好抽取 → 写入 L2 记忆(显式)/ 生成待确认候选(隐式)

Token 预算分配(必须硬性限制,否则成本会失控)

🔒 本表是 token 预算的唯一定义位置。FR-MEM-04、FR-AGT-03、产品方案 §2.4.2、用户系统 §3.8、穿搭 Agent §3.5.2/§10.2、T-P3-17 一律引用本表,不得复述数值。

⚠️ 此前存在两套互相矛盾的口径,本轮已查明原因并修正。原架构表写「会话摘要 ≤ 400、总输入 ≤ 3700」,用户系统 §3.8 写「会话上下文 ≤ 800、记忆注入合计 ≤ 1400」。错在架构表:用户系统的 800 是「最近 6 轮原文 + 更早轮次的滚动摘要」,而架构表只算了滚动摘要、漏掉了近轮原文。因此以用户系统 §3.8 的分项为准,并修正总输入合计。

层级 部分 预算 说明
总输入 系统提示词 ≤ 800 固定不变,放最前以最大化缓存命中
总输入 记忆注入(小计) ≤ 1400 展开见下四行;这是 FR-MEM-04 的验收口径
└ 记忆注入 画像摘要 L0/L1 ≤ 250 模板化压缩,非 LLM 生成
└ 记忆注入 偏好记忆 L2 ≤ 150 confidence ≥ 0.5 按置信度取 Top 15,硬禁忌优先保留
└ 记忆注入 事件记忆 L3(向量召回) ≤ 200 V2 能力,V1 预算预留但不使用
└ 记忆注入 会话上下文 L4 ≤ 800 = 最近 6 轮原文 ≤ 400 + 更早轮次滚动摘要 ≤ 400
总输入 检索知识 ≤ 1500 重排后取前 N 条,超出则截断而非全塞
总输入 用户当前输入 ≤ 500 超长提示精简
总输入合计 ≤ 4200 FR-AGT-03 的验收口径;原 3700 因漏算近轮原文而偏低
输出 ≤ 800 超长回答不利于阅读,也贵

V1 实际用量:L3 不启用,故记忆注入 ≤ 1200、总输入 ≤ 4000,留有余量。

裁剪优先级(预算超限时按此顺序丢弃,不得报错):事件记忆 L3 → 滚动摘要尾部 → 检索知识低分项 → 偏好记忆低置信项 → 近轮原文最早的几轮。硬禁忌与安全约束永不裁剪 —— 裁掉它们会导致推荐用户明确拒绝的品类,属 P0 缺陷(产品方案 §8.3.3 要求禁忌违反率为 0)。

缓存前缀纪律:系统提示词与稳定知识片段必须放在 prompt 头部且不含时间戳、随机 ID、用户昵称等变量,否则缓存永远不命中,输入成本翻数倍(TD-04)。

7.3 换装任务

① 前置校验:单品是否 tryon_ready?用户照片是否合规且质量达标?
② 配额:check_quota → reserve
③ 创建 tk_task(type=tryon) → 入 gpu 队列
④ Worker:调 tryon-svc(带 idempotency_key),拿到 gpu_seconds
⑤ 结果图审核(IMS)
⑥ 合规出口:水印「AI 生成」+ 写入元数据与内容编号 → 存 COS 用户内容桶
⑦ commit 配额、记录成本、Push 通知
⑧ 失败:区分可重试(网络/排队超时)与不可重试(输入非法/审核拒绝),后者立即退还配额

队列即容量:gpu 队列的并发上限直接由 GPU 容量决定,并把「当前排队位次 + 预估等待」返回给用户。不要让请求无限积压——超过阈值直接拒绝新任务并提示稍后再试,这比让用户等 10 分钟体验更好。

7.4 配额消耗(V1)与 IAP 支付(V2)

V1:四张表的职责边界(必须先看这段,否则会实现成两套并行的扣减逻辑)

billing 域有四张表,此前文档没写清它们的关系,导致 bl_quota.used 与 bl_wallet.balance 看起来像两套重复机制。实际分工是:

表 在 V1 的角色 是否参与 V1 的扣减判定
bl_quota_rule 规则:每个 quota_key 的周期类型、基础额度、任务奖励上限、防刷硬上限 提供判定用的阈值,配置化,改配置不发版
bl_quota 周期计数器:(user_id, quota_key, period_key) 上的 used 与本周期已获得的 bonus_granted ✅ V1 的判定就在这张表上
bl_ledger 流水(真相):每一次发放、消耗、退还都留痕,供对账与 V2 定价分析 ❌ 不参与判定,但每次判定通过后必须写
bl_wallet 余额缓存:V1 语义为「跨周期不清零的可累积额度」 ⚠️ V1 仅"首次终身"类额度用它(如首次报告),周期类额度不用

一句话概括:V1 的判定看 bl_quota(周期计数器),V2 的判定才看 bl_wallet(点数余额)。bl_ledger 在两个版本里都只是流水。 之所以 V1 就把 bl_wallet/bl_ledger 建起来,是为了 V2 上支付时不迁移数据(§6.2),不是因为 V1 需要它们做判定。

判定公式中 task_bonus 的来源已明确:不是从 bl_ledger 实时聚合(那样每次判定都要扫流水,且并发下不可靠),而是在 bl_quota 上物化为 bonus_granted 字段,发放任务奖励时同时递增它。判定公式因此是纯单行读:

有效上限 = MIN(
    bl_quota_rule.base_limit + bl_quota.bonus_granted,   -- 基础额度 + 本周期已获奖励
    bl_quota_rule.hard_cap                                -- 防刷硬上限,任何情况不可超越
)
放行条件 = bl_quota.used < 有效上限

V1:配额消耗三段式

① 熔断检查:全局日成本水位是否已达 100%?(NFR-COST-02)
        ↓ 已熔断 → 直接拒绝,且【不得预扣】,返回"今日服务繁忙"
② 校验:SELECT ... FOR UPDATE 读 bl_quota 单行 → 按上方公式判定
        ↓ (服务端硬校验,客户端提示仅为体验,FR-BILL-06)
③ 预扣 reserve → bl_quota.used += N(同一事务内)
                 bl_ledger 写 delta=-N, tx_type=consume, status=reserved
        ↓
④ 任务执行(Celery,长耗时)
        ↓
成功:commit  → 流水 status=committed(bl_quota.used 不变,已在③计入)
失败:refund  → bl_quota.used -= N
                bl_ledger 写反向流水 delta=+N, tx_type=refund(带 idempotency_key)

发放:任务奖励 → bl_quota.bonus_granted += N(受 task_bonus_max 约束)
                bl_ledger 写 delta=+N, tx_type=system_grant
        ↓ (同一任务同一周期幂等,FR-BILL-03)

三处最容易写错的地方:

  1. 熔断必须在预扣之前(步骤①在③之前)。顺序颠倒会导致平台自身限流却扣掉用户额度 —— 这是 NFR-COST-02 里「配额净扣减 = 0」那条验收标准要防的情况。
  2. bl_quota.used 的增减必须与 bl_ledger 写入在同一个数据库事务里,否则对账永远不平。
  3. 周期重置靠 period_key 自然切换,不要写定时清零任务。period_key 形如 2026-08-13(日)/ 2026-08(月)/ lifetime(终身),新周期首次访问时插入新行即可。定时清零在跨时区、补偿执行、任务漏跑时都会出错。

为什么预扣而不是直接扣:长耗时任务可能失败,直接扣会产生「扣了额度没拿到结果」的客诉。先冻结再确认,失败自动释放。V1 虽然不涉及金钱,这个问题依然存在 —— 用户对"次数被白扣"的敏感度不比扣钱低,而且 V1 没有客服退款兜底手段,只能靠机制保证。

对账:所有变更都写流水,余额可由流水重算校验(每日定时,不一致则告警)。V1 就要做,否则 V2 上支付时对账逻辑得从零开发且无历史数据验证。

V2:IAP 支付(V1 不实现)

购买:客户端 IAP 下单 → 支付成功拿 purchase_token
        ↓
     POST /orders/verify (purchase_token)
        ↓
     服务端调华为 IAP 校验接口(**必须服务端校验**,不可信客户端结果)
        ↓
     UNIQUE(purchase_token) 保证只发货一次
        ↓
     发放点数/会员 → 写 bl_ledger(tx_type=purchase,带 idempotency_key)

V1→V2 的衔接成本被刻意压到最低:消耗侧逻辑(reserve/commit/refund)完全复用,只需新增「购买」这一条发放路径。这是 §6.2 中坚持让 V1 与 V2 共用 bl_wallet / bl_ledger 的收益。

7.5 统一合规出口

所有对外生成物必须经过 compliance.publish_asset(),没有例外。

async def publish_asset(
    raw: bytes | str,
    content_type: Literal["image", "text", "pdf"],
    ref: ContentRef,
    model_info: ModelInfo,
) -> PublishedAsset:
    # 1. 内容审核(fail-close:审核服务不可用则拒绝发布)
    # 2. 生成 27 位内容编号并登记 cp_content_registry
    # 3. 显式标识:图片加可见「AI 生成」水印;文本加提示语
    # 4. 隐式标识:写入文件元数据(属性信息 + 服务提供者编码 + 内容编号)
    # 5. 上传目标 COS 桶,返回带签名的访问地址

必须专门测试的点:图片经过 CDN、缩略图处理、客户端保存与再次分享后,元数据是否仍然存在。很多图片处理链路会剥离 EXIF/XMP,一旦剥离就等于没做隐式标识(TD-21)。


8. AI 能力层设计

8.1 LLM 网关

class LLMGateway:
    async def complete(
        self,
        scene: Scene,                  # 场景决定模型档位、超时、预算
        messages: list[Message],
        schema: type[BaseModel] | None, # 需要结构化输出时传 Pydantic 模型
        stream: bool = False,
        user_id: int | None = None,
    ) -> Completion | AsyncIterator[Chunk]:
        ...

内置能力:

能力 实现要点
场景化路由 scene → (provider, model, temperature, max_tokens, timeout) 全部配置化,改模型不改代码
故障转移 主供应商超时/5xx/限流 → 自动切备用;连续失败触发熔断,冷却后半开探测
结构化输出 传入 Pydantic Schema,网关负责 JSON Schema 约束 + 解析失败重试 + 校验
Prompt 版本 Prompt 存文件(随代码版本化)+ 场景绑定版本号;A/B 时按用户哈希分流
成本计量 每次调用写 ob_ai_call,含缓存命中 token 数
预算保护 场景级日预算 + 用户级频控;超限降级到轻量模型或拒绝
审核联动 输入输出审核在网关内统一完成,业务方无需关心
可复现 记录 prompt 版本 + 模型版本 + 参数,便于回溯「为什么当时这么答」

8.2 视觉服务

POST /internal/vision/analyze
  ├─ segment_portrait  → 腾讯云 SegmentPortraitPic → 前景掩膜
  ├─ body_keypoints    → RTMPose ONNX → 关键点(肩/髋/踝定高)
  ├─ face_landmarks    → 腾讯云 AnalyzeFace(90点) / AnalyzeDenseLandmarks(888点,仅全面报告)
  ├─ face_attributes   → 腾讯云 DetectFaceAttributes(Skin/Hair/Shape/Eye/...)
  ├─ color_sampling    → 自研:按关键点定位采样区,转 Lab,稳健统计(去高光/阴影)
  └─ body_measure      → 自研:掩膜宽度剖面法(TD-06)
返回:结构化特征 + 每项置信度 + 质量问题标记(模糊/遮挡/多人/姿态异常)

质量门禁前置:图片质量不达标(多人、遮挡、侧脸过大、光线过暗)应在分析前就返回明确的重拍指引,而不是硬算出一个低置信度结果。用户宁愿重拍一次,也不愿收到一份错的报告。

8.3 混合检索的实现

核心是一条 SQL 完成硬过滤 + 向量召回(这正是选 pgvector 的收益):

WITH filtered AS (
  SELECT c.chunk_id, c.entity_id, c.text, c.embedding, e.attrs
  FROM kb_chunk c
  JOIN kb_entity e ON e.entity_id = c.entity_id
  WHERE e.status = 'published'
    AND e.entity_type = ANY(:entity_types)
    AND (:occasion IS NULL OR e.attrs->'occasions' ? :occasion)
    AND NOT (e.attrs->'avoid_body_shapes' ? :body_shape)   -- 硬禁忌直接排除
),
vec AS (
  SELECT chunk_id, 1 - (embedding <=> :query_vec) AS vec_score
  FROM filtered ORDER BY embedding <=> :query_vec LIMIT 50
),
kw AS (
  SELECT chunk_id, ts_rank(tsv, plainto_tsquery('simple', :query_text)) AS kw_score
  FROM kb_chunk WHERE tsv @@ plainto_tsquery('simple', :query_text) LIMIT 50
)
SELECT ... -- RRF 融合,再叠加规则权重与新鲜度

重排权重(可配置,需用黄金集调参):最终分 = 0.45×向量 + 0.2×关键词 + 0.25×规则权重 + 0.1×新鲜度。规则命中的条目要有明显加权——专业规则的可信度高于语义相似度,这是自建知识库的意义所在。

8.4 记忆系统的读写

读(注入):

get_memory_snapshot(user_id, budget_tokens)
  → 优先级排序:L0 身份 > L1 画像 > L2 显式偏好 > L5 衣橱 > L3 事件
  → 过滤:status='active' AND confidence >= 阈值
  → 裁剪到预算内 → 缓存(hash 变更才重建)

写(置信度初值的唯一事实源是《用户系统与记忆系统-需求文档》§3.5,本处原写 0.95 与之冲突,已更正为 0.90):

用户确认 / 设置页配置 → confidence=1.00
对话中明确陈述        → confidence=0.90,立即生效,回执告知用户「已记住」
报告产出(机器诊断)  → confidence=诊断置信度(高置信维度 0.85 / 争议维度 0.65),写 L1
自评问卷              → confidence=0.60
行为推断(隐式)      → confidence=0.50,累积证据达阈值生成 status='pending_confirm'
                        → 在合适时机征询确认,确认后才转 active(且 confidence 置 1.0)

衰减与冲突:定时任务按 decay_after 降低未被强化的记忆置信度;同 key 冲突时显式 > 报告 > 隐式,时间新 > 时间旧,并写 pf_memory_event 留痕。用户在「我的记忆」页面的编辑拥有最高优先级且不可被自动覆盖。


9. API 设计规范

9.1 基本约定

项 约定
基础路径 规范写法为 /api/v1,大版本进路径。/v1/* 作为等价别名由中间件重写到 /api/v1/*,两种写法返回完全一致的响应;文档、客户端与新代码一律写 /api/v1(别名只为兼容早期任务描述中的 /v1,不要在新代码里使用)
风格 面向资源的 REST;流式对话用 SSE(text/event-stream)
认证 Authorization: Bearer <access_token>(JWT,15 分钟)+ 刷新令牌(服务端可撤销)
幂等 写操作支持 Idempotency-Key 头,服务端 24 小时内保证同键同结果
分页 游标分页(cursor + limit),不用 offset
时间 全部 ISO 8601 UTC,客户端负责本地化
文档 FastAPI 自动生成 OpenAPI,契约先行:先定 schema 再写实现

9.2 统一响应

{ "code": 0, "message": "ok", "data": { }, "request_id": "..." }
{ "code": 40301, "message": "今日额度已用完", "data": { "required": 1, "remaining": 0, "reset_at": "..." },
  "request_id": "...", "hint": "明天恢复,或完成任务多换 3 次" }

错误码分段:4xxxx 客户端错误、5xxxx 服务端错误、6xxxx 外部依赖错误(便于监控区分「我们的问题」和「厂商的问题」)。每个错误码都要有用户可读的 message 和可选的 hint(告诉用户怎么办)——AI 产品的失败场景多,错误文案是体验的一部分。

9.3 主要接口清单

域 方法与路径 说明
认证 POST /auth/huawei POST /auth/refresh POST /auth/guest POST /auth/merge 登录、刷新、游客、游客合并
用户 GET/PATCH /me POST /me/consents DELETE /me(注销) 含同意记录与注销
上传 POST /uploads/presign 返回 COS 临时桶预签名 URL,图片不经应用服务器
报告 POST /reports GET /reports/{id} GET /reports POST /reports/{id}/share POST /reports/{id}/regenerate
画像 GET /profile GET /profile/memories PATCH /profile/memories/{id} DELETE /profile/memories/{id} 「我的记忆」可见可控
Agent POST /agent/conversations POST /agent/conversations/{id}/messages(SSE) POST /agent/messages/{id}/feedback
换装 POST /tryon/tasks GET /tryon/tasks/{id} POST /tryon/results/{id}/favorite
发型 GET /hairstyles POST /hairstyles/tasks
任务 GET /tasks GET /tasks/{id} POST /tasks/{id}/cancel 任务中心
知识 GET /kb/items GET /kb/items/{id} 只读对外
配额 GET /quota GET /quota/ledger POST /quota/tasks/{task_key}/claim V1;hint 文案不得含价格字样(FR-BILL-07)
支付 GET /products POST /orders/verify V2 起
埋点 POST /events/batch 客户端批量上报

10. 缓存策略

数据 位置 TTL 失效方式
记忆快照 Redis 1 小时 记忆写入时按 user_id 主动失效
知识检索结果 Redis 10 分钟 键含 query hash + 过滤条件 + 知识库版本号
规则集(已发布) 进程内 + Redis 5 分钟 发布时广播失效
色板 进程内 长期 版本号变更时重载
报告长图 COS + CDN 长期 报告版本变更生成新对象(不覆盖,便于回溯)
LLM 结果 不缓存业务层 — 依赖供应商 prompt 缓存降本,不做业务层结果缓存(个性化内容缓存意义不大)
用户配额 Redis 计数器 + PG 落账 周期 周期切换重置

知识库版本号是关键设计:所有检索缓存键都带上全局 kb_version,知识库发布时版本号 +1,所有旧缓存自然失效,不需要精确追踪哪些缓存受影响。


11. 安全设计

11.1 认证与授权

  • JWT 短期 access token(15 分钟)+ 服务端可撤销的 refresh token;登出/注销时撤销全部会话。
  • 所有资源访问必须校验归属(report.user_id == current_user.id),不能只靠 ID 不可猜。越权是这类应用最常见的漏洞。
  • 后台采用独立账号体系与独立域名/网段,不与用户端共用鉴权。

11.2 数据安全

数据 措施
人脸原图 临时桶、服务端加密、2 小时生命周期、处理后立即删除、访问全程走预签名 URL
诊断结论 属敏感个人信息衍生数据,数据库加密存储敏感字段,日志中禁止打印
结果图 私有桶 + CDN 签名 URL(短期有效)+ 防盗链,禁止公开可读
密钥 全部走 SSM/KMS,禁止进代码、镜像、环境变量明文
日志 脱敏中间件:手机号、UnionID、图片 URL、诊断结论一律脱敏或不记录
备份 PG 自动备份 + 定期恢复演练(没演练过的备份等于没有备份)

11.3 防刷与滥用

风险 措施
免费额度被批量刷取 设备指纹 + 华为账号绑定;同设备多账号限制;异常注册风控
换装接口被外部盗用 内网隔离 + 服务间令牌;对外接口强制登录 + 配额消耗
恶意图片攻击 上传前校验类型/尺寸/像素上限;解码走安全库;审核前置
Prompt 注入 用户输入与系统提示词严格分区;输出侧校验;禁止用户内容影响工具调用决策
爬取知识库 对外接口只暴露必要字段,加频控与签名

11.4 降级与熔断

每个外部依赖都要有明确的降级行为(见 §2 表格)。唯一不允许降级的是内容审核:审核服务不可用时按拦截处理(fail-close)。其他能力遵循 fail-soft,保证核心体验可用。


12. 性能与容量

12.1 性能目标(NFR)

链路 指标 目标
普通 API p95 响应 < 300ms
Agent 首字 p95 < 2s
Agent 整轮 p95 < 8s
初级报告生成 p50 / p95 < 45s / < 90s
全面报告生成 p95 < 180s(允许后台生成 + 推送)
换装出图 p95 < 40s(受 GPU 容量约束,排队时间单独统计)
知识检索 p95 < 200ms
长图渲染 p95 < 8s
可用性 月度 ≥ 99.5%(V1)

排队时间与执行时间必须分开统计。混在一起看会得出错误结论:明明是 GPU 容量不足(该扩容),却被误判为推理慢(去优化模型)。

12.2 容量假设与压力点

基线取 1 万 DAU。与产品方案 §8.1.1 的口径关系需说明清楚,否则会被误读为架构容量低于业务目标:

  • 产品方案的 V1 业务目标是 MAU 15 万,且明确不以 DAU 作为考核指标(形象诊断是低频决策型工具,改用季度回访率)。
  • 低频工具的 DAU/MAU 通常在 510%,因此 MAU 15 万对应 DAU 约 **0.751.5 万** —— 1 万 DAU 基线与业务目标是吻合的,不是保守估计。
  • 本基线的作用是确认架构不会在早期撞墙;实际压测值由 T-P5-06 确定,Agent 并发上限亦由此推导(穿搭 Agent §7.1)。
资源 估算 压力点
API QPS 峰值约 100~200 单机 FastAPI 多 worker 足够
报告生成 首日集中,后续每日新增用户量级 CPU 队列 + 视觉分析,可水平扩 worker
换装出图 最大瓶颈 GPU 数量决定吞吐,靠队列削峰 + 配额限制需求
PG 连接 需连接池(asyncpg pool + 上限保护) 长事务与 Worker 争用,必须分离读写池
向量检索 十万级向量 pgvector HNSW 足够,索引重建走低峰

13. 成本模型

架构上的硬性要求:每一次付费调用都必须落 ob_ai_call,并可归因到用户与功能。 没有这张表,成本优化只能靠猜。

⚠️ V1 不收费让这张表的地位更高,不是更低(TD-28)。V1 没有收入,因此成本是唯一的财务变量;同时 ob_ai_call 是 V2 定价的唯一数据来源 —— 单次真实成本与人均使用频次都从这里出。埋点缺失的功能,在 V2 定价时就是一个必须靠猜的空洞。这一项不允许"先上线后补埋点"。

13.1 三个必须分开的成本口径

⚠️ 本节原有一处错误论证,已更正。原文称「月度成本上限 = MAU × 单用户配额上限 × 单次成本,是可事前算准的确定值」。这不成立:按人头发配额约束的是「单用户能用多少」,而总成本 = MAU × 人均,MAU 本身没有上限。 配额防的是单用户刷爆,防不了总量涨爆。

口径 公式 MAU 15 万时 用途
理论最坏 MAU × 防刷硬上限成本(¥236/月) ≈ ¥3,540 万/月 只说明"配额不是预算工具",无实际预算意义
预期成本 Σ(各功能月用量推算 × 单次成本) ¥7~12 万/月 唯一的预算口径,含使用率假设
真实封顶 全局日成本熔断阈值 × 30 ¥15 万/月 唯一与用户规模无关的硬闸门

预期成本的完整算式与其隐含的使用率假设见产品方案 §5.3.1;单用户三档成本见产品方案 §5.2.1。单一事实源在产品方案,本节不重复数值。

13.2 单位成本建模

⚠️ LLM 单价自 2026-08-17 起分峰谷两档,本节的所有 C_llm 必须按调用时刻取价。 DeepSeek 高峰时段(北京时间 09:00-12:00、14:00-18:00)单价为空闲时段的 2 倍, 且新价目相对旧价目输出侧涨约 2.25~4.5 倍。两个直接后果:

  1. ob_ai_call.cost_cents 必须在调用当时算好落库,不能事后按「当前单价」回算 —— 否则同一条记录在不同时间重算会得到不同结果,V2 定价的依据就不可复现。 实现上由两套价目表 + 时段判定完成(T-P1-25c),并用 rate_tier 记录当次档位。
  2. §13.1 的预期成本与熔断阈值需按新单价重算一次。原数值基于旧单价推得, 而报告生成集中在白天高峰 —— 不重算会让熔断阈值落在错误的位置。

可控杠杆有两个:一是缓存前缀纪律(固定系统前缀命中缓存后输入侧大幅降价,已实测 单次命中 128/240 输入 token);二是把非实时的文案生成挪到空闲时段,直接省一半。

单位成本核算公式(数值需在 Phase 0 验证任务中实测填入,此处为建模框架):

功能 成本构成 建模公式
初级报告 人脸 API + 分割 API + 自建推理 + LLM + 审核 + 渲染 ≈ C_face + C_seg + C_llm(in≈8k, out≈3k) + C_mod×n + C_render
全面报告 初级 + 稠密关键点 + 更长文案 ≈ 初级 × 3~4
Agent 单轮 LLM(缓存命中后输入成本大幅下降)+ 检索 + 双向审核 ≈ C_llm(in≈4.2k 多数缓存, out≈0.8k) + C_mod×2。思考模式须显式关闭(T-P1-24a):开启后思考 token 按输出价计费,实测同一问答耗时从 1.8s 涨到 13.5s
换装单次 GPU 秒数 + 审核 + 存储 + CDN ≈ gpu_seconds × 单价 + C_mod + C_storage
抠图单件 GPU 秒数(离线批量摊薄) 批量跑,按批次成本 / 件数
短信验证码 单条约 ¥0.03~0.045(TD-32) 发送条数 × 单价。量级上可忽略,但必须计量并告警 —— 被刷时它是直接的现金损失,且不像 GPU 成本那样有配额兜着

13.3 三道成本闸门(按拦截范围从大到小)

# 闸门 拦截范围 触发后行为 需求编号
1 全局日成本熔断 平台总量 自动降级,不是仅告警 NFR-COST-02
2 场景级日预算 单个功能 该功能切轻量模型或暂停 NFR-COST-02
3 用户级配额 单个用户 服务端拒绝 FR-BILL-06

第 1 道是新增的,也是唯一真正封顶的一道(原设计只有"预警",见 §13.1 的更正)。实现要求:

  • 计数:Redis 日累计成本键(cost:daily:{yyyymmdd}),由 LLM 网关与 GPU 任务在成本产生后立即累加,日切自动过期。落库对账以 ob_ai_call 为准,Redis 只做实时判定。
  • 分级降级顺序(按"用户感知损失最小"排序,阈值百分比可配置):
日成本水位 动作 用户可感知的变化
60% 告警,不影响用户 无
80% 停高清导出、停报告重新生成 两个低频次要功能不可用
90% 停发型试戴;换装强制降画质 + 排队 次要生成能力不可用
100% 仅保留在途任务与纯文本对话;新的生成类请求全部拒绝 「今日服务繁忙,请明天再试」
  • 在途任务必须放行:成本已经付出,中断只会浪费掉且让用户白等。熔断只拦新请求。
  • 关键场景需显式豁免:少数调用一旦失败会让整个链路无法继续(例如意图识别 —— 拿不到意图就无法路由, 用户看到的是功能完全坏掉而不是降级)。这类场景在场景配置上标记为 critical,不受熔断拒绝, 但仍照常计入日成本。豁免清单必须极短且逐个论证,否则熔断会被绕空。
  • 必须与配额解耦:熔断拒绝的请求不得扣减用户配额(走 refund 流水,FR-BILL-05),否则用户会因平台原因损失额度。这是最容易写错的一处。
  • 必须可人工干预:运营后台需有熔断状态查看与手动解除开关(FR-ADM-*),不能只能等日切。

14. 部署架构

14.1 V1 部署(单可用区,Docker Compose)

腾讯云 VPC
├─ CLB(公网入口,TLS 终止)
├─ CVM-app(2~4 核)
│   ├─ nginx
│   ├─ api        (FastAPI × N workers)
│   ├─ admin      (极简运营后台)
│   ├─ worker-cpu (Celery: cpu 队列)
│   ├─ worker-io  (Celery: io 队列)
│   ├─ beat       (定时任务,单实例)
│   └─ vision-svc (ONNX 推理)
├─ CVM-gpu(按需启停)
│   ├─ tryon-svc  (换装/发型推理)
│   ├─ worker-gpu (Celery: gpu 队列)
│   └─ matting    (批量抠图,仅素材生产期运行)
├─ 云数据库 PostgreSQL(含 pgvector)
├─ 云数据库 Redis
├─ COS × 4 桶 + CDN
└─ CLS / 监控告警

GPU 实例按需启停是 V1 最有效的成本手段:换装量小的时候没必要 7×24 常驻。实现方式是队列有积压时拉起、空闲一段时间后释放(配合任务中心的排队体验,用户可接受冷启动的额外等待)。

14.2 环境

环境 用途 数据
local 本地开发 Docker Compose 起 PG/Redis/COS 模拟;AI 能力走 mock 或少量真实调用
dev 联调 独立库;外部 API 用测试账号与低配额
staging 预发/验收 结构与生产一致,保留可供监管抽查的测试通道与虚拟测试账号(备案已完成,但变更备案与日常抽查仍需,TD-19)
prod 生产 —

14.3 发布

  • 容器镜像 + 标签化版本;数据库迁移在发布流程中作为独立步骤执行(先迁移后发布,保证向后兼容)。
  • 迁移必须向后兼容(加列不删列、先双写后切读),避免回滚时数据不兼容。
  • 灰度:按用户哈希分流;报告与 Agent 这类核心链路的 Prompt/规则变更必须先灰度 + 看黄金集回归。

15. 可观测性

类型 工具 关键内容
链路追踪 OpenTelemetry 一次报告生成的完整 span 树(含各外部调用耗时),排障必需
指标 Prometheus + Grafana 三张看板:业务漏斗、AI 成本、任务健康(TD-24)
日志 CLS 结构化 JSON,带 request_id/user_id/task_id 贯穿
审计 cp_audit_log 后台操作、知识库变更、权限变更
告警 云监控 + 企业微信/飞书 分级:P0(服务不可用/审核失效)、P1(任务失败率超阈值/成本突增)、P2(延迟劣化)

必须能一键回答的三个问题(这是可观测性的验收标准):

  1. 「某用户说他的报告生成失败了」→ 用 user_id 找到 task,看到失败在哪一步、错误码、配额是否已退还。
  2. 「昨天成本涨了 3 倍」→ 按功能/模型分组的成本对比,定位到具体场景。
  3. 「换装最近变慢了」→ 区分是排队变长(扩容)还是推理变慢(模型/资源)。

16. 工程规范

16.1 仓库结构

meida_backend/             # 后端仓库。文档在独立仓库 meida,鸿蒙端尚未建库
├─ apps/
│  ├─ api/                 # FastAPI 应用(路由、依赖注入、中间件)
│  ├─ worker/              # Celery 任务定义
│  └─ admin/               # 极简运营后台
├─ services/
│  ├─ vision/              # 视觉推理服务
│  ├─ matting/             # 抠图批处理
│  └─ tryon/               # 换装服务(改造纳管)
├─ packages/
│  ├─ domain/              # 领域模型与业务规则(纯逻辑,无 IO、无框架,可纯单测)
│  ├─ shared/              # 配置、日志、错误、DB、COS、可观测
│  ├─ llm/                 # LLM 网关
│  │                       # ── 以下为 §4.1 的 11 个业务域,每域一个包 ──
│  ├─ identity/            # 账号与会话
│  ├─ billing/             # 配额与计量
│  ├─ task/                # 任务中心
│  ├─ profile/             # 用户画像
│  ├─ memory/              # 记忆系统
│  ├─ kb/                  # 知识库
│  ├─ retrieval/           # 混合检索
│  ├─ rules/               # 规则引擎
│  ├─ report/              # 美学报告
│  ├─ agent/               # 穿搭 Agent
│  ├─ tryon/               # 换装与发型编排
│  ├─ wardrobe/            # 衣橱
│  ├─ notify/              # 通知推送
│  └─ compliance/          # 审核 / 水印 / 元数据标识
├─ prompts/                # Prompt 模板(版本化,随代码走)
├─ migrations/             # Alembic
├─ tests/
│  ├─ unit/                # 领域逻辑
│  ├─ integration/         # 带 DB/Redis(testcontainers)
│  └─ golden/              # 黄金集回归(检索/规则/报告)
├─ deploy/                 # Dockerfile / compose / CI 配置
└─ scripts/

文档集在 meida 仓库(docs/),不进本仓库。鸿蒙客户端独立建库,不预置空目录。

包内约定:每个业务域包统一为 service.py(用例编排,对外唯一入口)+ repo.py(该域自己的表访问)

  • 可选 schemas.py。§4.2 的「禁止直接查对方的表」因此落为一条可机检规则: 跨域只允许 import 对方的 service,不允许 import 对方的 repo。

三层的判别标准(决定新代码该放哪一层):

层 判别标准 反例
packages/domain 纯函数与不变量,不 import 任何框架、不做 IO 把 SQLAlchemy 模型放进来
packages/<域> 该域的用例编排与自己的表访问 在 agent/ 里直接读 bl_quota 表
apps/ HTTP / Celery 的适配,不含业务判断 在路由函数里写配额判定公式

这三条边界由 import-linter 契约强制,不靠 code review。分层规则一旦只靠人守,第一次赶工就会破。

16.2 AI 辅助开发下的质量防线

既然主要由 AI 编码,人工 review 的带宽会成为瓶颈,因此必须把规范变成机器可执行的检查:

防线 内容 卡关方式
契约先行 接口先写 Pydantic schema 与 OpenAPI,再写实现 客户端类型由 OpenAPI 生成,schema 变更即可见
静态检查 ruff(lint+format)+ mypy strict(覆盖 packages/domain、packages/llm) CI 失败即阻断合并
分层依赖检查 用 import-linter 之类的工具声明层间依赖规则 跨域直接访问对方表 → CI 报错
黄金集回归 检索准确率、规则命中正确性、报告结构完整性、禁忌违反数=0 每次 PR 跑,指标退化即阻断
迁移检查 Alembic 迁移必须可逆或明确标注不可逆 Review 检查清单
敏感信息扫描 密钥/Token 扫描 pre-commit + CI

黄金集是最重要的一道:AI 改代码时最容易破坏的是那些「没有断言保护的隐性行为」。检索链路和规则引擎必须有一套固定输入 → 期望输出的样本集,这既是质量防线,也是《美学知识库-建设方案》中质量保障章节的落地形式。


17. 架构演进路线

阶段 架构形态 触发条件
V1 模块化单体 + 独立 AI 服务;单机 Compose;PG 单库 —
V1.5 读写分离;Redis 集群;GPU 自动伸缩 报告/换装量上升,PG 读压力显现
V2 拆出 llm-gateway、retrieval-svc 为独立服务;引入 TKE 需要独立发布节奏或独立扩容
V2 多端(iOS/Android)→ 重新评估跨端框架 明确的多端商业需求(TD-01)
V3 向量迁 Qdrant/Milvus;事件流引入消息队列;数仓引入 ClickHouse 向量 > 500 万 / 跨域事件复杂度上升 / 需要即席分析

演进纪律:每一次架构升级都必须先出现可测量的瓶颈,再动手。提前架构化是这个阶段最大的浪费。


18. 架构决策记录(ADR 索引)

ADR 决策 详见
ADR-01 客户端用鸿蒙原生 ArkTS,不用跨端框架 TD-01
ADR-02 业务域用模块化单体,AI 能力独立服务 §3.2
ADR-03 向量检索用 pgvector,不引入专用向量库 TD-08
ADR-04 图谱用 PG 邻接表 + 递归 CTE TD-09
ADR-05 规则引擎自研数据驱动决策表 TD-10
ADR-06 人体关键点自建(腾讯云已下线) TD-05
ADR-07 体型测算用掩膜宽度剖面法 TD-06
ADR-08 抠图用 BiRefNet,禁用 RMBG-2.0 TD-07
ADR-09 自建 LLM 网关,双供应商路由 TD-04
ADR-10 人脸原图不落盘,只存派生特征 TD-20
ADR-11 统一合规出口,所有生成物必经 TD-21
ADR-12 报告长图服务端渲染 TD-12
ADR-13 配额预扣-确认-退还三段式;V1 与 V2 共用账本表 §7.4、TD-28
ADR-14 统一任务中心承载全部长耗时任务 §7

19. 技术风险登记

风险 影响 概率 应对
备案登记周期拖延上线 最高 已消除 ✅ 备案已完成,此风险关闭(TD-19)
备案范围与实际调用的模型不一致 高:超范围提供服务 中 核实备案覆盖的模型清单;LLM 网关已做多路由抽象,必要时 V1 先单路由(TD-19 残留项)
素材自采产能不足 高:tryon_ready < 300 件则「建议→试穿」闭环不成立 中高 备案解除后这是最长工序(TD-26)。按周产能倒排,未达标则功能降级为「加入搭配」
全职顾问到岗延迟 中:规则库启动即延后,M2 顺延 中 Phase 0 最早启动招聘(TD-27、T-P0-20)
团队缺乏 ArkTS 经验 前端进度不确定 中 第一个任务就打通端到端骨架,尽早暴露问题
体型测算准确率不达标 报告核心结论不可信 中 Phase 0 验证任务(≥80% 一致率);不达标则降级表述 + 引入人工校准
换装成功率依赖白底图素材 核心闭环卡住 高 素材生产列为 Phase 1 前置任务,先小批量走通再规模化
GPU 成本随活跃度线性增长 单位经济恶化 低(V1) V1 不收费,配额为硬上限,月度成本上限 = MAU × 单用户配额成本,可事前算准。V2 引入付费后此风险重新升级
大模型调价或能力变动 成本与质量波动 中 网关抽象 + 双供应商 + 场景配置化
云 API 下线(已发生一次) 能力缺口 中 核心能力(关键点、抠图)自建;对云能力保留替换预案
AI 标识元数据在链路中被剥离 合规不达标 中 专项测试覆盖 CDN/压缩/客户端保存全路径
知识库内容生产跟不上 建议质量低、可解释性弱 高 知识缺口埋点驱动优先级;顾问资源尽早接洽(TD-27)

20. 与需求文档的映射

本文章节 对应需求文档
§7.1 报告生成链路 《美学报告-需求文档》§6 生成流程
§7.2 Agent 链路、§8.3 混合检索 《穿搭Agent-需求文档》§3.4、《美学知识库-建设方案》§6
§6.2 profile 域、§8.4 记忆读写 《用户系统与记忆系统-需求文档》§3
§6.2 kb 域、§8.3 《美学知识库-建设方案》§2~§6
§7.4 配额与支付 《用户系统与记忆系统-需求文档》§2.4/2.5、《需求规格说明》§2.9
§7.5、§11 《合规与安全方案》全文
§13 成本模型 《产品方案》§5.2 成本结构

相关文档


变更记录

日期 版本 变更
2026-08-14 v1.4 文档 ↔ 代码交叉评审回写。① §16.1 根目录 meida/ → meida_backend,并去掉本仓库并不存在的 docs/、client-harmony/。② §4.1 补「域与包不是一一对应」:产品职责上记忆归 profile,代码上独立 packages/memory。③ bl_quota 列清单补 limit_value(本周期 base_limit 快照),并给出 quota_key 与产品方案 §3.2 的一一映射;游客 key 与记忆条数明确不进种子。④ ob_ai_call 补保留口径(定价完成前不可按日志周期删除)
2026-08-13 v1.3 脚手架落地后按实现回写,五处修正。① §16.1 仓库结构补全 11 个业务域包 —— 原树只列了 7 个 packages/,§4.1 定义的 11 个业务域在树里无处安放,实现时只能猜;现补全并加「包内约定」(每域 service.py + repo.py,跨域只许 import 对方 service)与三层判别标准表。② §6.2 ob_ai_call 补 prompt_id/prompt_version/tokens_reasoning/rate_tier 四列 —— §8.1 要求 Prompt 版本化可复现,但表里没有版本列,等于要求做不到的事;思考 token 混进 tokens_out 会掩盖开关思考模式的成本差异。③ §9.1 澄清基础路径 —— 正文写 /api/v1、任务描述写 /v1,实现两者都要能用;现明确 /api/v1 为规范写法、/v1/* 仅作兼容别名。④ §13.2 新增峰谷计价约束 —— DeepSeek 自 8-17 起高峰单价翻倍且新价目输出侧涨 2.25~4.5 倍,成本须在调用当时算好落库(不可事后回算),§13.1 的预算与熔断阈值需按新价重算;Agent 单轮成本注明思考模式须显式关闭。⑤ §13.3 补「关键场景显式豁免」 —— 意图识别这类调用失败会让链路整体不可用,须标记 critical 不受熔断拒绝,但仍计入成本;豁免清单必须极短,否则熔断被绕空
2026-08-13 v1.2 文档一致性评审修订,其中三处是会直接卡住开发的实质缺陷。① §7.4 补齐 billing 域四张表的职责边界 —— bl_quota 与 bl_wallet 此前看起来像两套重复机制,task_bonus 的来源也没定义;现明确「V1 判定看 bl_quota、V2 判定看 bl_wallet、bl_ledger 两版都只是流水」,并把 task_bonus 物化为 bl_quota.bonus_granted 字段(避免每次判定聚合流水),补充三处最易写错的地方(熔断须在预扣之前、used 增减须与流水同事务、周期重置靠 period_key 而非定时清零)。② §13 成本模型重写 —— 推翻「月度成本上限 = MAU × 单用户配额上限」这个错误论证(配额约束单用户,总成本 = MAU × 人均,MAU 无上限),改为「理论最坏 / 预期成本 / 真实封顶」三口径,并新增 §13.3 四档熔断降级(含在途任务放行、被熔断请求不得扣配额、可人工解除)。③ §7.2 token 预算改为嵌套表,合计 3700→4200(原表漏算会话近轮原文 400),并明确硬禁忌永不裁剪。另:pf_memory.status/source、id_consent.consent_type 枚举与用户系统对齐(personalization 不可省略,否则记忆写入无合规依据);手机号存储位置明确为 id_user_identity;诊断维度 34→32;points_reserved→quota_reserved;外部依赖表补入腾讯云短信并说明登录双通道不得互相依赖;§12.2 说明 1 万 DAU 基线与 MAU 15 万目标的口径关系
2026-08-13 v1.1 按业务决策收口调整。billing 域降级为「配额与计量」:V1 移除支付、订单、会员、IAP;bl_point_tx 改名 bl_ledger 并新增 tx_type 字段,使 V1 配额账本与 V2 点数账本共用同一张表(V2 免数据迁移);新增 bl_quota_rule 配额规则表。§7.4 拆为「V1 配额三段式」与「V2 IAP 支付」。§13 成本模型补充「V1 成本上限可事前算准」的公式,并强调 ob_ai_call 是 V2 定价的唯一数据来源、不允许后补。§19 风险登记:备案风险关闭,新增备案范围一致性、素材自采产能、顾问到岗三项风险
2026-08-13 v1.0 首次输出。确立「模块化单体 + 独立 AI 服务」架构、十个业务域数据模型、五条关键链路、统一合规出口、V1 单机 Docker Compose 部署与成本模型