Files
zclaw_openfang/wiki/data-model.md
iven c10e50d58e docs(wiki): Phase D完成 — 6模块页重构(routing/chat/butler/hands-skills/pipeline/data-model)
- routing.md: 移除Store/lib列表+5节模板 (330→131行)
- chat.md: 添加集成契约+不变量 (180→134行)
- butler.md: 移除重复→引用memory/hands-skills (215→150行)
- hands-skills.md: 5节模板+契约+不变量 (281→170行)
- pipeline.md: 添加契约+重组 (157→154行)
- data-model.md: 添加契约+双库架构图 (181→153行)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 21:53:17 +08:00

154 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 数据模型
updated: 2026-04-22
status: active
tags: [module, database, schema]
---
# 数据模型
> 从 [[index]] 导航。关联模块: [[saas]] [[memory]]
## 1. 设计决策
**WHY 双存储架构**: PostgreSQL 适合 SaaS 多租户场景 — 42 表支持用户隔离、计费、审计、知识库。SQLite 适合桌面端单用户 — 零配置、嵌入式、本地记忆无需网络。两者完全隔离,通过 SaaS relay + 配置同步桥接。
**WHY 42 PostgreSQL 表**: 按领域划分为认证(5)、Provider(6)、计费(5)、知识库(7)、其他(19) 五大域,每个域内部高内聚,域间通过外键约束保证引用完整性。
**WHY FTS5 (SQLite 全文搜索)**: 本地记忆搜索需支持中文。FTS5 的 trigram 分词器原生支持 CJK 字符,无需外部依赖。配合 TF-IDF 权重排序,兼顾搜索精度和零配置部署。
**WHY 迁移系统**: SaaS 用 SQL 文件迁移 (21 up + 17 down),本地 SQLite 用 schema.rs 程序化迁移。两种策略分别匹配各自部署场景 — PG 需要运维可控的 SQL 脚本SQLite 需要应用内自动迁移。
**WHY pgvector (deferred)**: knowledge_chunks 表已创建 pgvector 索引,为将来 embedding 语义搜索预留。当前记忆搜索走 FTS5 + TF-IDF足够满足中文场景。embedding 激活需要 LLM embedding API 调用,尚未排期。
## 2. 关键文件 + 数据流
### 核心文件
| 文件 | 职责 |
|------|------|
| `crates/zclaw-saas/migrations/` | 21 up SQL 迁移 (42 CREATE TABLE) |
| `crates/zclaw-saas/src/models/` | PostgreSQL 数据模型 struct 定义 |
| `crates/zclaw-memory/src/schema.rs` | SQLite schema 定义 + 程序化迁移 |
| `crates/zclaw-memory/src/store.rs` | SQLite 会话/消息存储 (20 tests) |
| `crates/zclaw-memory/src/user_profile_store.rs` | 用户画像存储 (20 tests) |
| `crates/zclaw-memory/src/trajectory_store.rs` | 轨迹存储 (9 tests) |
| `crates/zclaw-growth/src/storage/sqlite.rs` | FTS5 + TF-IDF 记忆存储 (6 tests) |
| `docker-compose.yml` | PostgreSQL 容器配置 |
### 双库架构
```
PostgreSQL (SaaS, 42 表) SQLite (本地, 2 库)
┌─────────────────────────┐ ┌──────────────────────────┐
│ 认证: accounts/tokens │ │ data.db: │
│ Provider: keys/models │ │ agents, sessions, │
│ 计费: plans/invoices │ │ messages, kv_store, │
│ 知识库: items/chunks │ │ facts, user_profiles, │
│ 配置/日志/Webhook │ │ trajectory_events, │
│ 行业: industries │ │ hand_runs │
└─────────────────────────┘ ├──────────────────────────┤
↑ SaaS API │ memories.db: │
│ relay_tasks │ memories (FTS5), │
│ usage_records │ metadata │
└──────────────────────────┘
↑ 本地 API
```
### 集成契约
| 方向 | 接口 | 说明 |
|------|------|------|
| Called by ← saas | PostgreSQL 连接池 (sqlx) | 所有 SaaS API 端点通过连接池访问Pool 大小可配置 |
| Called by ← memory | SQLite/FTS5 连接 (rusqlite) | 记忆提取/检索/注入 通过 zclaw-memory + zclaw-growth |
| Provides → growth | TF-IDF + FTS5 索引 | zclaw-growth 调用 FTS5 全文搜索 + TF-IDF 语义评分 |
| Called by ← kernel | schema.rs 程序化迁移 | 桌面端启动时自动执行 SQLite 迁移,版本由 schema_version 表跟踪 |
| Provides → butler | user_profiles + facts | 管家模式读取用户画像和提取事实进行上下文注入 |
## 3. 代码逻辑
### PostgreSQL 域划分 (42 表)
**认证域 (5 表)**: `accounts` (邮箱/密码/pwv/角色) → `api_tokens`, `refresh_tokens` (JWT 单次使用), `roles`, `permission_templates`
**Provider 域 (6 表)**: `providers``models` (白名单), `provider_keys` (加密 API Key 池), `key_usage_window` (RPM/TPM 滑动窗口), `model_groups``model_group_members` (故障转移组)
**计费域 (5 表)**: `billing_plans``billing_subscriptions` (用户订阅) → `billing_invoices``billing_payments`, `billing_usage_quotas` (实时递增配额)
**知识库域 (7 表)**: `knowledge_categories` (自引用树) → `knowledge_items``knowledge_chunks` (pgvector 向量), `knowledge_versions`, `knowledge_usage`, `structured_sources``structured_rows`
**其他域 (19 表)**:
| 子域 | 表 | 说明 |
|------|-----|------|
| API & Relay | `account_api_keys`, `usage_records`, `relay_tasks` | API Key/用量/异步任务 |
| 配置 | `config_items`, `config_sync_log` | KV 配置/同步日志 |
| Prompt | `prompt_templates`, `prompt_versions`, `prompt_sync_status` | 模板/版本/同步 |
| Agent | `agent_templates` | Agent 模板配置 |
| 设备 | `devices` | 设备管理 |
| 遥测 | `operation_logs`, `telemetry_reports`, `saas_schema_version` | 操作日志/统计/版本 |
| 调度 | `scheduled_tasks` | 定时任务 |
| 限流 | `rate_limit_events` | 限流事件 (持久化到 PG) |
| Webhook | `webhook_subscriptions`, `webhook_deliveries` | Webhook 订阅/投递 |
| 行业 | `industries`, `account_industries` | 行业配置/账户关联 |
### SQLite 本地存储
**data.db** (`zclaw-memory/schema.rs`): agents, sessions, messages, kv_store, facts, user_profiles, trajectory_events, compressed_trajectories, hand_runs, schema_version
**memories.db** (`zclaw-growth/storage/sqlite.rs`): memories (uri, memory_type, content, keywords, importance, access_count), metadata (KV)
### FTS5 虚拟表
```sql
CREATE VIRTUAL TABLE memories_fts USING fts5(uri, content, keywords, tokenize='trigram');
```
> trigram 分词器从 unicode61 迁移,原生支持 CJK。零结果时 fallback 到 LIKE 搜索。
### 不变量
> **SaaS 用 PostgreSQL本地记忆用 SQLite两者完全隔离。** 数据不自动同步,仅通过 SaaS relay API 手动触发。
> **FTS5 使用 trigram 分词器,中文搜索依赖正确分词。** 极短查询 (1-2 字) 可能 fallback 到 LIKE。
> **data.db 与 memories.db 是两个独立的 SQLite 数据库。** zclaw-memory 管理 data.db (会话/画像)zclaw-growth 管理 memories.db (记忆/FTS5)。跨库查询不适用,数据交换通过 Rust API。
### 测试链路
| 功能 | 测试文件 | 测试数 |
|------|---------|--------|
| SaaS 全模块 | `crates/zclaw-saas/tests/` (17 文件) | 集成测试 |
| SQL 迁移 | `crates/zclaw-saas/migrations/` (21 up) | 启动时自动执行 |
| 本地存储 | `zclaw-memory/src/store.rs` | 20 |
| 用户画像 | `zclaw-memory/src/user_profile_store.rs` | 20 |
| 轨迹存储 | `zclaw-memory/src/trajectory_store.rs` | 9 |
| 记忆存储 | `zclaw-growth/src/storage/sqlite.rs` | 6 |
## 4. 活跃问题 + 注意事项
| 优先级 | 问题 | 说明 |
|--------|------|------|
| P2 | pgvector embedding 未激活 | knowledge_chunks 表索引就绪generate_embedding Worker 逻辑 deferred |
| P3 | FTS5 CJK 极短查询 | trigram 已启用1-2 字查询可能 fallback 到 LIKE待真实用户反馈 |
| — | 迁移幂等性 | PG 迁移用 `IF NOT EXISTS`SQLite 迁移用 schema_version 表跟踪 |
**注意事项**: PostgreSQL 连接需要 `ZCLAW_DATABASE_URL``saas-config.toml` 中的 `database_url` 配置。本地 SQLite 数据库文件存储在 Tauri 应用数据目录下,卸载应用会丢失数据。`schema.rs` 中的 SQLite 迁移通过 `schema_version` 表跟踪版本号,仅执行增量迁移,不会重建已存在的表。环境变量 `DB_PASSWORD` 支持 `saas-config.toml``${VAR_NAME}` 插值引用。
## 关联模块
- [[saas]] — PostgreSQL 由 SaaS 后端管理,所有 API 端点的数据源
- [[memory]] — SQLite 本地记忆存储 + FTS5 全文搜索 + TF-IDF 权重
- [[routing]] — relay_tasks 异步任务追踪,连接前端请求和 SaaS 后端
- [[security]] — 数据加密: provider_keys AES-256-GCM, 密码 Argon2id, TOTP 独立加密密钥
## 5. 变更日志
> 最近 5 条与数据模型相关的变更。完整日志见 [[log]]。
| 日期 | 变更 |
|------|------|
| 2026-04-22 | 跨会话记忆修复: profile_store 连接 + 双数据库统一 + 诊断日志 |
| 2026-04-21 | Phase 0+1: 经验积累 reuse_count 修复 + 跨会话检索增强 IdentityRecall 26→54 模式 |
| 2026-04-19 | TRUTH.md 数字校准: 42 CREATE TABLE, 38 迁移文件, Rust 101,967 行 |
| 2026-04-17 | E2E 测试: 记忆去重+记忆注入+invoice_id+agent隔离修复 |
| 2026-04-15 | Heartbeat: health_snapshot 统一收集器,删除 intelligence-client/ 9 废弃文件 |