系统架构设计文档
「吃什么」决策助手 — 技术架构总览 v1.0 文档版本:v1.0 关联 PRD:PRD-v1.0.md 编写日期:2026-05-18
一、系统架构概览
1.1 整体架构图
┌──────────────────────────────────────────────────────────────┐
│ 用户层(WeChat Mini Program) │
│ 首页 │ 搜索页 │ 盲盒页 │ 人群页 │ 详情页 │ 个人中心 │
└──────────────────────────────────────────────────────────────┘
│
│ HTTPS / JSON API
▼
┌──────────────────────────────────────────────────────────────┐
│ API 网关层 │
│ 统一入口 · 鉴权 · 限流 · 路由 │
└──────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 推荐服务 │ │ 菜谱服务 │ │ 用户服务 │
│ (Recommend) │ │ (Dish) │ │ (User) │
│ │ │ │ │ │
│ · F1 食材搜索 │ │ · F4 菜谱详情 │ │ · 收藏管理 │
│ · F2 盲盒推荐 │ │ · F5 营养查询 │ │ · 偏好设置 │
│ · F3 人群推荐 │ │ · F6 季节节日 │ │ · 搜索历史 │
│ · F7 场景推荐 │ │ │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
└───────────────────┼───────────────────┘
▼
┌──────────────────────────────────────────────────────────────┐
│ 数据层 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 菜品库 │ │ 用户库 │ │ 节日历 │ │ 推荐日志│ │
│ │ MongoDB │ │ MySQL │ │ Redis │ │ ClickHouse│ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└──────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ AI / 数据处理层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 菜谱爬虫系统 │ │ 菜谱清洗/结构化│ │ 营养数据计算 │ │
│ │ (Python爬虫) │ │ (AI+LLM) │ │ (营养API) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 推荐算法引擎 │ │ 意图识别引擎 │ │
│ │ (规则+CF) │ │ (NLP) │ │
│ └──────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────┘
二、技术栈选型
2.1 前端(小程序)
| 技术 | 选型 | 说明 |
|---|---|---|
| 框架 | 原生小程序 / Taro | MVP 阶段用原生,跨平台时切换 Taro |
| 状态管理 | MobX / Redux | 管理用户状态和推荐上下文 |
| UI 组件 | Vant Weapp | 有赞出品的轻量组件库 |
| 动画 | Lottie / wx.createAnimation | 盲盒动画 |
| 网络请求 | Fly.js | 统一请求拦截和错误处理 |
2.2 后端
| 技术 | 选型 | 说明 |
|---|---|---|
| 框架 | Node.js (Express/Koa) 或 Python (FastAPI) | 推荐 FastAPI,Python 方便 AI 集成 |
| API 风格 | RESTful + GraphQL(部分场景) | REST 作为主协议 |
| 网关 | Kong / Nginx | 限流、鉴权、路由 |
| ORM | Prisma(Node)/ SQLAlchemy(Python) | 类型安全 |
2.3 数据存储
| 存储 | 选型 | 用途 |
|---|---|---|
| 菜品数据库 | MongoDB | 菜品非结构化数据,灵活扩展 |
| 用户数据 | MySQL | 用户信息、收藏、偏好 |
| 缓存 | Redis | 热门菜品缓存、Session、节日数据 |
| 日志/分析 | ClickHouse | 用户行为日志、推荐效果分析 |
| 对象存储 | 阿里云 OSS / 腾讯云 COS | 菜品图片 CDN |
2.4 AI 层
| 能力 | 技术选型 | 说明 |
|---|---|---|
| 菜谱清洗/结构化 | LLM API(GPT-4 / 通义千问) | 将爬取的原始数据转为结构化字段 |
| 意图识别 | 轻量 NLP 模型 / 关键词匹配 | 识别用户模糊输入的意图 |
| 营养数据计算 | 本地营养数据库 + AI 辅助 | 参考 USDA 食物营养数据库 |
| 相似菜品推荐 | 向量数据库(Milvus) | 语义相似菜品匹配 |
三、数据模型设计
3.1 核心实体关系
┌─────────────┐ ┌─────────────┐
│ User │ │ Dish │
├─────────────┤ ├─────────────┤
│ id │──┐ │ id │
│ nickname │ │ │ name │
│ avatar │ │ │ coverImage │
│ crowdType │ │ │ ingredients │
│ preferences │ │ │ nutrition │
│ createdAt │ │ │ steps │
└─────────────┘ │ │ crowdType │
│ │ │ scenes │
│ │ │ seasons │
│ │ │ festivals │
▼ │ │ createdAt │
┌─────────────┐ │ └─────────────┘
│ Collection │ │ │
├─────────────┤ │ │
│ id │ │ │
│ userId │──┘ │
│ dishId │─────────────┘
│ createdAt │
└─────────────┘
3.2 菜品索引设计
MongoDB 菜品集合需建立复合索引:
// 食材搜索索引
db.dishes.createIndex({ "ingredients.name": 1 })
// 人群推荐索引
db.dishes.createIndex({ crowdType: 1, "nutrition.calories": 1 })
// 季节节日索引
db.dishes.createIndex({ seasons: 1, festivals: 1 })
// 场景索引
db.dishes.createIndex({ "sceneTags.suitableScenes": 1, "sceneTags.maxDuration": 1 })
// 全文搜索索引(菜品名、描述)
db.dishes.createIndex({ name: "text", description: "text" })
四、核心服务设计
4.1 推荐服务(Recommendation Service)
核心职责:聚合所有推荐场景(F1/F2/F3/F6/F7),输出统一推荐结果
interface RecommendService {
// F1: 食材搜索推荐
searchByIngredients(ingredients: string[], filters?: Filter): Promise<Dish[]>;
// F2: 盲盒推荐
mysteryBox(mode: 'global' | 'category' | 'crowd', context?: any): Promise<Dish>;
// F3: 人群定向推荐
recommendForCrowd(crowdType: string, formData: any): Promise<Dish[]>;
// F6: 季节节日推荐(叠加层)
applySeasonalBoost(dishes: Dish[]): Dish[];
// F7: 场景推荐
recommendByScene(sceneContext: SceneContext): Promise<Dish[]>;
}
推荐流程:
用户请求
│
▼
意图识别(判断是哪种推荐场景)
│
├── F1 食材搜索 → 食材匹配引擎
├── F2 盲盒 → 随机抽取引擎 + 防重复
├── F3 人群推荐 → 人群规则引擎
├── F6 季节节日 → 时令加权层
└── F7 场景推荐 → 场景过滤引擎
│
▼
综合排序(融合多维度得分)
│
▼
返回结果 + 记录日志
4.2 菜谱服务(Dish Service)
核心职责:菜品 CRUD、营养数据查询
interface DishService {
getDishDetail(id: string): Promise<DishDetail>;
getNutritionInfo(dishId: string, servingSize?: number): Promise<Nutrition>;
compareNutrition(dishIds: string[]): Promise<NutritionCompare>;
getRelatedDishes(dishId: string, limit?: number): Promise<Dish[]>;
getDishesByTags(tags: string[], page?: number): Promise<Dish[]>;
}
4.3 用户服务(User Service)
核心职责:用户信息、收藏、偏好管理
interface UserService {
getUserProfile(userId: string): Promise<User>;
updateCrowdPreference(userId: string, crowdType: string, formData: any): Promise<void>;
collectDish(userId: string, dishId: string): Promise<void>;
uncollectDish(userId: string, dishId: string): Promise<void>;
getCollections(userId: string, page?: number): Promise<Dish[]>;
recordSearchHistory(userId: string, ingredients: string[]): Promise<void>;
}
五、API 接口设计
5.1 接口目录
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/v1/search/ingredients | F1 食材搜索 |
| POST | /api/v1/mystery-box/open | F2 开盲盒 |
| POST | /api/v1/recommend/crowd | F3 人群推荐 |
| GET | /api/v1/dish/:id | F4 菜品详情 |
| GET | /api/v1/dish/:id/nutrition | F5 营养详情 |
| POST | /api/v1/dish/compare | F5 营养对比 |
| GET | /api/v1/seasonal/current | F6 当前季节节日 |
| GET | /api/v1/festival/:festivalId | F6 节日专题 |
| POST | /api/v1/recommend/scene | F7 场景推荐 |
| GET | /api/v1/user/collections | 用户收藏列表 |
| POST | /api/v1/user/collect | 收藏菜品 |
| DELETE | /api/v1/user/collect/:dishId | 取消收藏 |
5.2 统一响应格式
interface ApiResponse<T> {
code: number; // 0 = 成功,其他 = 错误码
message: string; // 错误信息
data: T; // 响应数据
timestamp: number; // 时间戳
requestId: string; // 请求追踪 ID
}
// 示例
{
"code": 0,
"message": "success",
"data": { ... },
"timestamp": 1747564800000,
"requestId": "req_abc123"
}
5.3 错误码规范
| 错误码 | 说明 |
|---|---|
| 0 | 成功 |
| 1001 | 参数错误 |
| 1002 | 鉴权失败 |
| 2001 | 菜品不存在 |
| 2002 | 菜品库为空 |
| 3001 | 推荐服务异常 |
| 3002 | 推荐结果为空 |
| 5001 | 服务器内部错误 |
六、AI 数据处理流水线
6.1 菜谱采集流程
1. 确定数据源网站列表(美食天下、下厨房等)
│
▼
2. AI 生成爬虫脚本(Python + requests + BeautifulSoup)
│
▼
3. 批量抓取原始菜谱数据(HTML)
│
▼
4. 数据清洗
├── 去除 HTML 标签
├── 标准化食材格式(如「2个鸡蛋」→「鸡蛋 2个」)
└── 去重(根据菜名+主料指纹)
│
▼
5. LLM 结构化处理(GPT-4 / 通义千问)
└── 将非结构化文本转为标准 Dish 数据模型
│
▼
6. 营养数据估算
├── 匹配 USDA 食物营养数据库
└── AI 辅助计算整道菜营养成分
│
▼
7. 质量抽检
├── 每 50 道随机抽检 1 道
└── 人工审核 + 反馈修正
│
▼
8. 入库 MongoDB
6.2 数据质量指标
| 指标 | 目标值 |
|---|---|
| 爬取成功率 | > 95% |
| 字段完整率 | > 90%(必填字段) |
| 营养数据准确率 | > 85%(抽检) |
| 每日新增菜品 | 500-1000 道(MVP 期) |
七、部署架构(MVP 阶段)
7.1 最小化部署
┌──────────────────────────────────────┐
│ 微信小程序 │
└──────────────────────────────────────┘
│
│ HTTPS
▼
┌──────────────────────────────────────┐
│ 阿里云 / 腾讯云 │
│ │
│ ┌──────────────────────────────┐ │
│ │ Nginx (反向代理) │ │
│ │ + SSL 证书 │ │
│ └──────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────┐ │
│ │ Docker Compose (单节点) │ │
│ │ │ │
│ │ [API Service] │ │
│ │ [Recommendation Service] │ │
│ │ [MongoDB] │ │
│ │ [Redis] │ │
│ │ [MySQL] │ │
│ └────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────┐ │
│ │ 阿里云 OSS (CDN) │ │
│ │ 菜品图片存储 + 分发 │ │
│ └────────────────────────────────┘ │
└──────────────────────────────────────┘
7.2 扩容路径
| 阶段 | 架构变化 |
|---|---|
| MVP | 单节点 Docker Compose |
| 增长期 | 服务拆分、K8s 编排、多节点 |
| 成熟期 | 微服务架构、数据库读写分离、CDN 加速 |
八、关键非功能性指标
| 指标 | 目标值 | 说明 |
|---|---|---|
| API 响应时间 P99 | < 500ms | 99% 请求在 500ms 内返回 |
| 推荐接口响应时间 P99 | < 1s | 含复杂计算 |
| 盲盒开盒响应 | < 2s | 含动画加载 |
| 服务可用性 | > 99.9% | 核心接口 |
| 图片加载时间 | < 2s | 配合 CDN |
| 系统可支撑 DAU | 10万 | MVP 阶段目标 |
九、复核检查项
| 检查点 | 状态 |
|---|---|
| 前端技术栈选型合理(小程序原生/Taro) | ✅ |
| 后端技术栈支持 AI 集成 | ✅ |
| 数据存储选型合理(MongoDB/MySQL/Redis) | ✅ |
| 推荐服务架构覆盖所有 5 个推荐场景 | ✅ |
| API 接口设计完整 | ✅ |
| AI 数据流水线完整 | ✅ |
| 错误码规范统一 | ✅ |
| 部署架构可落地 | ✅ |
| 非功能指标可量化 | ✅ |
| 扩容路径清晰 | ✅ |