第02章:架构设计与数据建模——用一张图说清楚你要建什么

第02章:架构设计与数据建模——用一张图说清楚你要建什么


2.1 先画架构,再写代码

多数餐饮连锁的数字化失败,不是因为技术不行,而是因为一开始就没想清楚要建什么。

“我们需要一个智能客服”——这句话听起来清晰,实际上模糊到无法执行。什么叫智能?覆盖哪些场景?数据从哪来?谁来维护?

这一章解决的是落地前的最后一公里:用需求表驱动架构,用架构指导数据建模。读完这一章,你应该能拿出一张清晰的系统架构图,以及一套可以直接落地的数据表结构。


2.2 需求采集:从老板的一句话到可执行的需求表

2.2.1 需求访谈三问法

问任何一个餐饮老板"你想要什么样的智能化",回答往往是模糊的。

真正有效的方式是从具体场景出发,用三问法挖掘:

第一问:这件事现在谁在做?怎么做?花多少时间?
  → 找出最大的效率损失点

第二问:这件事做不好的时候,会出什么乱子?
  → 找出最高优先级的场景

第三问:这件事做好了,最明显的标志是什么?
  → 找出可量化的成功指标

2.2.2 需求表模板

编号 功能名称 需求描述 当前痛点 优先级 成功指标 涉及数据
F01 客户记忆 记住常客的口味偏好和上次点单 员工记不住,老顾客感觉被当新人 P0 复购率提升10% 客户档案、消费记录
F02 智能订货 系统自动生成订货建议 订货靠经验,损耗高 P0 食材损耗率降5% 销售数据、库存、天气
F03 飞书机器人 店长群自动汇报经营数据 每天手动统计数据 P1 数据汇报时间减少80% 订单、库存、人员
F04 内容生成 自动生成朋友圈/点评文案 文案靠人工写,效率低 P1 内容产出量提升3倍 菜品数据、节日日历
F05 复购触达 沉睡客户自动激活 沉睡客户没有系统化管理 P2 沉睡客户激活率15% 客户生命周期数据

2.3 系统架构设计

2.3.1 整体架构图

                    ┌─────────────────────────────┐
                    │        飞书客户端           │
                    │  (总部群/店长群/门店群)    │
                    └──────────────┬──────────────┘
                                   │  机器人 WebHook
                    ┌──────────────▼──────────────┐
                    │       OpenClaw Agent       │
                    │   (Skill 调度 + 对话管理) │
                    └───────┬──────────────┬───────┘
                            │              │
              ┌─────────────▼──┐    ┌─────▼──────────────┐
              │  PostgreSQL    │    │     ChromaDB       │
              │  (结构化数据)   │    │    (向量知识库)    │
              │  客户/订单/库存 │    │  菜品知识/SOP/话术 │
              └────────────────┘    └────────────────────┘
                            │              │
              ┌─────────────▼──────────────▼─────┐
              │        FastAPI 后台服务           │
              │  /orders  /customers  /dishes   │
              │  /inventory  /reports  /feishu   │
              └───────────────────────────────┘
                            │
              ┌─────────────▼──────────────┐
              │      Streamlit 前台         │
              │  经营看板 / 知识库管理       │
              │  订货建议 / 客户查询         │
              └─────────────────────────────┘

2.3.2 数据流分层

用户请求(飞书/企微/前台)
       │
       ▼
  OpenClaw Skill 调度
       │
       ├── 意图识别
       │    ├── 查询类 → Text-to-SQL → PG
       │    ├── 推荐类 → RAG检索 → ChromaDB
       │    ├── 操作类 → API调用 → FastAPI → PG
       │    └── 生成类 → LLM + 知识库 → 生成内容
       │
       ▼
  结果组装 + 合规校验 + 记忆更新
       │
       ▼
  返回用户(文字/卡片/数据报表)

2.4 多门店数据模型设计

2.4.1 核心实体关系

store(门店)
  ├── customer(客户)  1:N(一家门店多个客户)
  ├── orders(订单)    1:N
  ├── inventory(库存) N:1
  └── staff(员工)     1:N

customer
  ├── customer_memories(客户记忆向量)  1:1
  ├── orders(订单)                     1:N
  ├── member_cards(会员卡)             1:N
  └── lifecycle(生命周期状态)           1:1

dish(菜品)
  ├── dish_tags(菜品标签)              N:N
  ├── recipe(配方)                     1:1
  └── dish_allergies(禁忌关联)        N:N

2.4.2 多门店数据隔离策略

每家门店只能访问自己的数据,通过 store_id 字段强制隔离:

-- 所有涉及门店数据的查询,必须带 store_id 条件
-- 应用层强制注入:

WHERE store_id = :current_store_id

-- 店长角色:只看自己门店
-- 总部角色:可以看所有门店(特殊权限)
-- 员工角色:只看自己负责的客户(通过 create_user 关联)

2.5 数据库选型决策

2.5.1 什么时候用 PostgreSQL,什么时候用 ChromaDB

PostgreSQL(pgvector)擅长:

  • 结构化查询:客户档案、订单数据、库存台账
  • 事务处理:订单下单、库存扣减(原子性保证)
  • 精准条件过滤:门店=北京、客单价>100、订单日期=今天
  • SQL 聚合统计:GROUP BY、HAVING、子查询

ChromaDB(向量库)擅长:

  • 语义相似度搜索:“我想吃点不辣的” → 找到所有清淡菜品
  • 知识库检索:查询菜品卖点话术、服务SOP
  • 客户记忆语义搜索:搜索"上次带小孩来"相关的客户记忆
  • 非结构化内容匹配:模糊描述 → 精准结果

两者组合使用:

ChromaDB:存知识(菜品卖点、SOP、话术)
         存客户记忆向量(口味偏好、消费习惯的语义表示)

PostgreSQL:存业务主数据(客户、订单、库存)
            存向量索引锚点(对应 ChromaDB 的 ID)

2.6 建表SQL规划

2.6.1 建表顺序(依赖关系)

第一波(基础数据)
  → stores(门店)
  → dishes(菜品)
  → suppliers(供应商)

第二波(客户与交易)
  → customers(客户档案)
  → orders(订单主表)
  → order_details(订单明细)
  → customer_lifecycle(生命周期)

第三波(运营支撑)
  → inventory(日库存)
  → purchase_orders(采购单)
  → remind_tasks(待办任务)
  → feishu_channels(飞书频道配置)

第四波(知识库)
  → service_sop(服务SOP)
  → service_scripts(话术库)
  → dish_embeddings(菜品向量 — ChromaDB)
  → customer_memories(客户记忆向量 — ChromaDB)

2.6.2 最简可运行表结构(10张核心表)

-- 完整建表语句见附录B,以下为核心10张:

CREATE TABLE stores (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100), region VARCHAR(50),
    manager_name VARCHAR(50), feishu_group_id VARCHAR(100),
    is_active BOOLEAN DEFAULT TRUE
);

CREATE TABLE customers (
    id SERIAL PRIMARY KEY, store_id INTEGER REFERENCES stores(id),
    name VARCHAR(100), phone VARCHAR(30),
    preference_tags TEXT[],       -- 口味偏好标签:微辣/不要香菜/小孩份
    last_order_id INTEGER,
    member_level VARCHAR(20) DEFAULT '普通',  -- 普通/银卡/金卡/钻石
    lifetime_value DECIMAL(12,2) DEFAULT 0,
    lifecycle_stage VARCHAR(20) DEFAULT '新客',  -- 新客/活跃/沉睡/流失
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY, store_id INTEGER REFERENCES stores(id),
    customer_id INTEGER REFERENCES customers(id),
    order_time TIMESTAMP DEFAULT NOW(),
    total_amount DECIMAL(10,2),
    is_set_meal BOOLEAN DEFAULT FALSE,
    source VARCHAR(20)  -- 堂食/外卖/团购
);

CREATE TABLE order_details (
    id SERIAL PRIMARY KEY, order_id INTEGER REFERENCES orders(id),
    dish_id INTEGER, quantity INTEGER, unit_price DECIMAL(10,2)
);

CREATE TABLE dishes (
    id SERIAL PRIMARY KEY, store_id INTEGER REFERENCES stores(id),
    name VARCHAR(100), category VARCHAR(50),
    price DECIMAL(10,2), cost DECIMAL(10,2),
    is_recommended BOOLEAN DEFAULT FALSE,
    tags TEXT[]  -- 标签:辣/清淡/儿童适用/招牌
);

CREATE TABLE inventory (
    id SERIAL PRIMARY KEY, store_id INTEGER REFERENCES stores(id),
    dish_id INTEGER, current_qty DECIMAL(10,2),
    unit VARCHAR(20), last_restock DATE
);

CREATE TABLE customer_lifecycle (
    customer_id INTEGER PRIMARY KEY REFERENCES customers(id),
    lifecycle_stage VARCHAR(20),
    churn_probability DECIMAL(5,2),  -- 流失概率 0~1
    last_stage_change TIMESTAMP,
    recommended_action TEXT
);

CREATE TABLE supplier_scores (
    id SERIAL PRIMARY KEY, supplier_id INTEGER,
    score_type VARCHAR(50), score DECIMAL(3,2),
    evidence TEXT, created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE feishu_channels (
    id SERIAL PRIMARY KEY, store_id INTEGER REFERENCES stores(id),
    channel_type VARCHAR(20),  -- 总部群/店长群/门店群
    feishu_chat_id VARCHAR(100), is_active BOOLEAN DEFAULT TRUE
);

CREATE TABLE remind_tasks (
    id SERIAL PRIMARY KEY, customer_id INTEGER REFERENCES customers(id),
    task_type VARCHAR(50), content TEXT,
    remind_time TIMESTAMP, is_sent BOOLEAN DEFAULT FALSE
);

2.7 章节实施检查清单

完成本章后,你应该:

  • [ ] 有1张手绘的系统架构图(哪怕是草图)
  • [ ] 有一份填写完整的需求优先级表(哪怕只有3行)
  • [ ] 确认了 PostgreSQL 和 ChromaDB 的组合方案
  • [ ] 理解了多门店数据隔离策略
  • [ ] 运行了核心10张表的建表SQL
  • [ ] 明确了第一期上线的功能优先级(应该是 F01+F03,即客户记忆+飞书机器人)

本章小结

架构设计的核心就三件事:

  1. 需求表驱动:不要先想技术方案,先把场景和优先级说清楚
  2. PG+ChromaDB 双库协同:结构化查询用 PG,语义搜索用 ChromaDB
  3. 门店级数据隔离:所有数据查询强制带 store_id,权限兜底从设计第一天做起

下一章,我们开始构建第一章的核心能力:长期记忆系统。