私有产品 · 脱敏案例 · 迭代中
Ecom Image · 电商 AI 素材工作台
电商素材的「采集 → 参考 → 生成 → 审核 → 交付」全链路工作台,正在从本地工具硬化为可公开试用的多租户服务。
- 角色
- 独立开发 · 单人
- 周期
- 2026.07 – 至今(高强度迭代中)
- 规模
- 私有仓库 · 52 commits
- 状态
- 发布门槛驱动 · 暂未公开
背景问题
电商素材生产有三个真实痛点:版本爆炸——同一商品要按国家 / 平台出不同风格版本的图,靠人工管理 prompt 和产物很快失控;参考驱动——好图不是凭空生成的,运营需要先看热卖商品在卖什么图,把爆款图沉淀为可参考的视觉资产;成本与质量要闭环——每次生成都有算力成本,交付前要有质量检查,公开给外部用户前更要有身份、隔离、配额、账本。
以某海外电商设计 SaaS 为对标做功能 parity,但品牌、后端实现、模型路由、算力计费体系全部自有。当前处于持续迭代中,不是一次性 demo。
系统边界
运行时形状:Next.js Web UI + 统一 Python API(单进程)+ Postgres / Redis / MinIO。
| 层 | 职责 |
|---|---|
| Web(Next.js) | 首页灵感流、主工作台、AI 工具工作台(画布内联 AI 编辑);只做同源 /api/* 代理,浏览器不直连任何模型 SDK |
| 统一 API(Python 单包多模块) | projects(主链路 + 任务执行器)、prompts(模板 + 风格档案)、model_gateway(通道路由)、billing(估价 → 账本)、qa(质量检查)、assets(资产 + 存储代理)、crawler(采集调度)、auth(身份与租户)、brand_profiles |
| 基础设施 | Postgres(元数据)、Redis(队列)、MinIO(图像对象,私有桶 + 签名 URL) |
- 主产品链路:Project → MarketVersion → GenerationJob → DeliveryAsset,一个商品一个项目、一个市场一个版本、交付资产全链血缘可追溯。
关键决策
- 1
抛弃 n8n 与多服务拆分,收敛为单包模块化 FastAPI
编排引擎对单人迭代是负资产——类型、测试、部署全部收敛到一个 Python 包(按领域分模块),入口只有一个 uvicorn 应用。早期 n8n 编排已从运行时完全移除(仅保留归档 JSON,不加载)。
- 2
模型通道(Channel)抽象,而非绑定单一模型
一个 Channel = 一条到上游的连接(认证、端点、模型列表、能力标签、优先级);支持 OpenAI 兼容 / Gemini / 阿里百炼 / 火山方舟(豆包)多类 provider,按能力路由 + 失败自动 fallback;密钥只存引用名(api_key_ref),不存明文;MOCK 模式仅作开发兜底,明确不属于产品验收能力。
- 3
爆款采集 → 参考图的资产治理
内嵌 APScheduler 调度(cron 化业务配置),两层幂等去重(来源+外部 ID、来源 URL),爆款图与参考图分库分标签,「加入参考集」显式升格;参考图 + 地区平台风格档案 + 版本化模板共同组装 prompt。
- 4
无 mock 占位原则
后端核心链路必须真实实现,不允许用 mock 伪装项目、任务、资产、计费——这是写进仓库规则的硬约束。
- 5
Supabase 只做身份签发,授权永远在自有 API
FastAPI 用 JWKS 非对称验签(签名 / issuer / audience / 过期 / kid 全验),不信任浏览器传来的 email / role;本地只存 subject 映射,不存密码。
- 6
邀请制受控公开试用,先硬化后开放
邀请码只存 HMAC-SHA256 指纹、防重放、持久化限流、同一本地事务内消费;上游建号后本地失败会触发补偿删除,失败则 critical 告警;运营重置密码必须填理由并写脱敏审计事件。
- 7
发布门槛清单驱动(release-gate-driven)
公开试用前必须逐项通过 6 大类检查——身份访问、租户隔离与存储、credits 与执行(报价 / 预占 / 扣减 / 释放全幂等 + 不可变账本)、运营 console、生产运行时、staging 演示证据(含跨租户负测试)。每一项要求留证据,未过门不开放。
查看脱敏架构图(Mermaid 源码) ›
架构图使用通用角色标注,无竞品名称、凭据与租户数据。
%% Ecom Image 脱敏架构图(公开版 · 2026-07 现役运行时)
%% 不含竞品名、真实域名、密钥、供应商内部细节
flowchart TB
User([运营 / 设计者])
Operator([平台运营者])
subgraph Web["Web UI · Next.js"]
Insp["灵感流首页<br/>热卖参考"]
Bench["主工作台<br/>Project → MarketVersion → Job → DeliveryAsset"]
Tools["AI 工具工作台<br/>画布内联 AI 编辑"]
Web2["同源 /api/* 代理<br/>浏览器不直连模型 SDK"]
end
subgraph API["统一 Python API · FastAPI 单进程(ecom 包)"]
Auth["auth<br/>JWT 验签(JWKS) · 邀请激活<br/>租户隔离 · 审计"]
Projects["projects<br/>主链路 + 任务执行器"]
Prompts["prompts<br/>模板 + 地区风格档案组装"]
Gateway["model_gateway<br/>Channel 抽象 · 能力路由 · fallback<br/>密钥只存引用"]
Billing["billing<br/>估价 → 报价/预占/扣减/释放 → 账本"]
QA["qa<br/>质量检查"]
Assets["assets<br/>资产 CRUD · 存储代理"]
Crawler["crawler<br/>内嵌调度 · 两层幂等去重<br/>爆款图 → 参考集升格"]
end
subgraph Infra["基础设施"]
DB[("Postgres<br/>元数据 / 租户 / 账本")]
Redis[("Redis<br/>队列支持")]
S3[("MinIO<br/>私有桶 + 签名 URL")]
end
IdP["身份提供方<br/>仅签发身份 · 授权在自有 API"]
Models["外部模型服务(多 provider)<br/>OpenAI 兼容 / Gemini / 百炼 / 方舟<br/>按能力路由"]
Sources["电商平台公开数据<br/>热卖榜 / 店铺 / 关键词"]
User --> Web
Web -->|同源| Auth
Auth --> IdP
Web --> Projects
Projects --> Prompts --> Gateway
Projects --> QA
Projects --> Assets
Gateway --> Billing
Crawler --> Sources
Crawler --> Assets
API --> DB
API --> Redis
Assets --> S3
Gateway --> Models
Operator -->|"console · 邀请 / 配额 / 通道管理<br/>敏感操作写脱敏审计"| Auth
验证方式
- 37 个 pytest 测试文件,覆盖 auth / assets / billing / brand_profiles / crawler / model_gateway / projects / prompts / shared;每次提交附带当次验证命令与结果(最近一轮 27 passed);
- Web 端 tsc --noEmit 类型零错误为提交前置;
- 生产运行时启动校验:缺 Supabase / Postgres / MinIO / 迁移 / 模型通道配置直接拒绝启动;
- 已知风险公开记录:部分设置 / 日志路由在租户隔离完成前不具备公开条件,明确标记为发布阻塞项。
可公开结果
- 状态声明:产品仍在迭代,公开试用发布门槛尚未全部通过(多租户资源隔离进行中),暂无公开 URL
- 测试证据随仓库维护;截图与演示将在发布门通过后以合成品牌素材录制
脱敏边界
以下内容不公开,本案例全文与配图均已规避:
- 对标竞品名称、竞品静态资源与抓取数据;
- 模型供应商凭据、供应商内部响应原文;
- 真实商家素材、未授权品牌元素;
- 真实邀请码、审计数据、租户数据;
- 截图 / 演示一律使用合成品牌与合成商品数据。