第一章 AI-Native SaaS的架构设计
第一章 AI-Native SaaS的架构设计
“一个好的架构,是把未来的变化成本提前算进去的设计。对于AI产品,这意味着:在一切还不确定的时候,做出灵活而非脆弱的选择。”
一、什么叫AI-Native
"AI-Native"这个词被过度使用了。很多产品给自己贴上AI-Native的标签,实际上只是把一个ChatGPT对话框嵌入了原有系统。这不叫AI-Native,这叫AI-Wrapper。
真正的AI-Native产品,AI不是附加的功能,而是产品核心价值的直接来源。这意味着:
- 核心用户流程依赖AI能力(而不是AI只在某个可选功能里出现)
- 产品的数据模型和业务逻辑是围绕AI输入输出设计的
- 系统的演进路线与AI能力的提升是耦合的
从架构角度,这带来了几个传统SaaS没有的挑战:
- 异步性:AI调用比数据库操作慢一到两个数量级,大量功能需要异步化处理
- 不确定性:AI输出不是确定性的,系统必须容忍并优雅处理"奇怪的"输出
- 成本可变性:用户使用越多,成本越高,而不是趋近于零
- 版本化:相同的输入,在不同模型版本下可能产生不同输出——历史数据的语义会漂移
本章从整体架构层面,描绘一个AI-Native SaaS系统应有的结构。
二、整体架构图
┌─────────────────────────────────────────────────────────────┐
│ 客户端层 │
│ Web App / Mobile App / API消费方 │
└────────────────────────┬────────────────────────────────────┘
│ HTTP/WebSocket
┌────────────────────────▼────────────────────────────────────┐
│ API 网关层 │
│ 认证 / 限流 / 路由 / 日志 / 访问控制 │
└──────────┬──────────────────────────────┬───────────────────┘
│ │
┌──────────▼──────────┐ ┌────────────▼───────────────────┐
│ 同步 API 服务 │ │ 异步任务服务 │
│ FastAPI Routes │ │ Celery Worker × N │
│ (≤5秒的请求) │ │ (后台处理, 批量任务) │
└──────────┬──────────┘ └────────────┬───────────────────┘
│ │
┌──────────▼──────────────────────────────▼───────────────────┐
│ 服务层 (Business Logic) │
│ AI服务 / 用户服务 / 额度服务 / 缓存服务 / 通知服务 │
└──────────┬────────────┬───────────────────────┬─────────────┘
│ │ │
┌──────────▼──┐ ┌──────▼───────┐ ┌───────────▼────────────┐
│ PostgreSQL │ │ Redis │ │ AI API 提供商 │
│ 主数据库 │ │ 缓存/队列 │ │ OpenAI / WaveSpeed / │
│ │ │ │ │ Anthropic 等 │
└─────────────┘ └─────────────┘ └────────────────────────-┘
│
┌──────────▼──────────────────────────────────────────────────┐
│ 对象存储层 │
│ 文件/图片/视频/AI生成内容 持久化 │
└─────────────────────────────────────────────────────────────┘
这个架构看起来和传统SaaS没有本质区别,关键在于几个专门为AI设计的组件:
三、核心组件详解
3.1 AI抽象层(AI Abstraction Layer)
直接在路由代码里调用OpenAI API是一种常见的初期做法,但这会带来后期的维护噩梦:
- 换一个供应商,需要改遍所有调用点
- 无法统一处理重试、超时、降级逻辑
- 成本追踪和日志记录分散
正确的做法是在服务层建立一个AI抽象:
# app/core/ai_client.py 概念性示例
class AIClient:
"""统一的AI API调用入口,屏蔽底层供应商差异"""
async def chat(
self,
messages: list[dict],
model: str = "auto", # 自动选择,或指定供应商/模型
response_format: str = "text",
max_tokens: int = 1000,
temperature: float = 0,
) -> AIResponse:
"""
统一的chat接口。内部处理:
- 供应商选择(OpenAI / Anthropic / 本地部署)
- 重试逻辑(指数退避)
- Token计数和成本记录
- 结构化日志
- 超时控制
"""
...
async def analyze_image(
self,
image_url: str,
prompt: str,
model: str = "gpt-4o-mini",
) -> AIResponse:
"""图像分析的统一接口"""
...
async def generate_image(
self,
prompt: str,
provider: str = "wavespeed", # 利用WaveSpeed访问多模型
model: str = "flux-kontext-dev-ultra-fast",
size: str = "1024x1024",
) -> GeneratedImage:
"""图像生成接口,默认路由到WaveSpeed"""
...
async def generate_video(
self,
image_url: str,
prompt: str,
model: str = "wan-2.7/image-to-video",
) -> AsyncJob:
"""视频生成(异步),通过WaveSpeed访问Wan/Seedance等模型"""
...
这个抽象的核心价值:所有AI调用都经过同一个入口,成本追踪、日志、重试在这里统一实现。
3.2 任务状态机(Task State Machine)
AI功能的异步性要求一套完善的任务状态管理。每个需要后台处理的AI任务,都应该有以下状态流转:
PENDING → PROCESSING → COMPLETED
→ FAILED → (可重试 → PENDING)
→ (不可重试 → PERMANENTLY_FAILED)
状态的数据结构:
# 任务记录表(概念)
class AITask(Base):
id: UUID
task_type: str # "image_analysis" / "video_generation" / ...
status: str # pending / processing / completed / failed
user_id: UUID
input_payload: dict # 输入参数(JSONB)
output_payload: dict # 输出结果(JSONB)
error_message: str | None
retry_count: int # 重试次数
cost_usd: float | None # 实际消耗成本
model_version: str | None # 使用的模型版本
created_at: datetime
started_at: datetime | None
completed_at: datetime | None
这张表是整个异步AI系统的中枢——前端轮询任务状态、后端写入进度、通知系统读取完成事件,都依赖它。
3.3 额度系统(Quota System)
AI SaaS区别于传统SaaS的核心之一:每次AI调用都有成本,用户的使用量与公司的支出直接挂钩。额度系统是控制这个风险的核心机制。
额度系统的设计需要支持:
- 多种额度类型(分析次数、生成时长、token数量)
- 多个计划层级(免费/基础/专业/企业)
- 额度重置周期(月度/年度/终身)
- 管理员超限覆盖
- 实时查询(不能有明显延迟)
实现细节在第五章详细讨论。这里只强调架构原则:额度检查必须在AI调用之前,额度扣减必须在AI调用成功之后(或在扣减后调用失败时立即回滚)。
3.4 内容存储层(Content Storage)
AI系统会产生大量内容:用户上传的原始素材、AI分析的结果、AI生成的图片/视频。这些内容的存储策略需要从第一天就想清楚:
| 内容类型 | 存储位置 | 访问方式 | 过期策略 |
|---|---|---|---|
| 用户上传文件 | 对象存储 | CDN公开URL | 按订阅计划保留X天 |
| AI分析JSON结果 | PostgreSQL JSONB | 直接读库 | 长期保留 |
| AI生成图片 | 对象存储 | CDN公开URL | 用户可手动删除 |
| AI生成视频 | 对象存储(分块) | 流式CDN URL | 按存储配额管理 |
| 临时处理文件 | 临时存储或内存 | 内部访问 | 处理完成后立即删除 |
四、关键设计决策
4.1 同步还是异步?
这是每个AI功能第一个需要回答的架构问题。判断框架:
| 条件 | 推荐模式 |
|---|---|
| 预计响应时间 < 3秒 | 同步 |
| 预计响应时间 3-10秒 | 同步(带进度条) |
| 预计响应时间 > 10秒 | 异步(后台任务+通知) |
| 批量处理多个输入 | 异步 |
| 处理时间高度不确定 | 异步 |
| 需要串联多个AI调用 | 异步 |
选择异步时,必须同时设计:
- 任务状态查询接口(前端轮询或WebSocket订阅)
- 完成通知机制(站内通知/邮件/Webhook)
- 失败重试机制
- 任务超时机制(防止任务永远停在processing状态)
4.2 AI输出存在哪?
AI分析一张图片,结果应该存在哪里?这个问题有两个维度:
- 全局层:按内容hash存储分析结果,相同图片任何用户触发后只存一份
- 用户层:记录每个用户是否已触发过分析,用于控制可见性
不要把这两层合并——它们有不同的访问模式和生命周期。
4.3 模型版本怎么管理?
AI模型会更新,Prompt会迭代。存储AI输出时,必须记录:
- 使用的模型版本(如
gpt-4o-2024-11-20) - 使用的Prompt版本(如
v2.3-image-analysis)
这两个版本号构成了AI输出的"技术坐标"。将来决定是否重新分析历史数据时,可以根据这个坐标判断哪些数据是"旧版"。
五、AI-Native架构的防腐层
一个容易被忽视的架构问题:当AI供应商更新了API、改了数据格式、调整了定价,你的系统如何不受影响?
防腐层(Anti-Corruption Layer,ACL) 是DDD(领域驱动设计)中的一个概念:在外部系统和你的核心域之间加一层转换,防止外部系统的概念"污染"你的核心模型。
对AI SaaS来说,防腐层意味着:
-
AI输出的内部表示:不直接存储OpenAI返回的原始格式,而是转换成你的内部数据模型后再存储。这样,供应商格式变化时,只需更新防腐层,而不是整个系统。
-
模型名称的内部映射:不在业务代码里硬编码
gpt-4o-mini,而是用内部标识符(如VISION_STANDARD),在配置层做映射。切换模型时,改一个配置,不改业务代码。 -
成本计算的统一接口:不同供应商的计费单位不同(OpenAI按token,WaveSpeed按图片/视频长度),在防腐层统一转换成内部成本单位(如分/美分)。
六、本章小结:架构选择清单
在开始写第一行业务代码之前,确认以下架构决策已做出:
- [ ] 核心AI功能是同步还是异步?
- [ ] 是否有AI抽象层,屏蔽供应商差异?
- [ ] AI输出的存储位置和格式(全局层+用户层分离)
- [ ] 模型版本的追踪和存储方案
- [ ] 额度系统的初步设计(哪几种额度,如何重置)
- [ ] 内容存储的分类和过期策略
- [ ] 任务状态机的数据结构
- [ ] 防腐层:内部模型与外部API格式的隔离方案
这个清单不需要在第一天全部完美解决,但每个问题都应该有一个初步的答案,并且随着产品演进持续更新。
下一章,我们深入技术栈——为什么FastAPI加异步PostgreSQL是构建AI SaaS的优秀选择,以及如何把异步的潜力真正发挥出来。