Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
- 创建 types.ts 定义完整的类型系统 - 重写 DocumentRenderer.tsx 修复语法错误 - 重写 QuizRenderer.tsx 修复语法错误 - 重写 PresentationContainer.tsx 添加类型守卫 - 重写 TypeSwitcher.tsx 修复类型引用 - 更新 index.ts 移除不存在的 ChartRenderer 导出 审计结果: - 类型检查: 通过 - 单元测试: 222 passed - 构建: 成功
308 lines
12 KiB
Markdown
308 lines
12 KiB
Markdown
# 开箱即用的上下文记忆库方案 (简化版)
|
||
|
||
## 一、背景与目标
|
||
|
||
### 1.1 问题
|
||
当前 ZCLAW 的 OpenViking 集成需要用户独立安装 Python 包 (`pip install openviking`),不是开箱即用的。
|
||
|
||
### 1.2 关键发现 ⚠️
|
||
经过深入分析,发现 **zclaw-growth crate 已经实现了核心功能**:
|
||
|
||
| 组件 | 文件 | 状态 |
|
||
|------|------|------|
|
||
| `VikingStorage` trait | `viking_adapter.rs` | ✅ 已实现 |
|
||
| `SqliteStorage` | `storage/sqlite.rs` | ⚠️ 只用内存缓存 |
|
||
| `SemanticScorer` (TF-IDF) | `retrieval/semantic.rs` | ✅ 已实现 |
|
||
| `MemoryExtractor` | `extractor.rs` | ✅ 已实现 |
|
||
| `MemoryRetriever` | `retriever.rs` | ✅ 已实现 |
|
||
| `PromptInjector` | `injector.rs` | ✅ 已实现 |
|
||
|
||
**问题**:`SqliteStorage` 虽然名字是 SQLite,但实际只用内存缓存(见 `storage/sqlite.rs:96-99`)。
|
||
|
||
### 1.3 修订目标
|
||
- **完善现有实现**:让 `SqliteStorage` 真正持久化到 SQLite
|
||
- **集成 TF-IDF**:使用已有的 `SemanticScorer` 提供语义搜索
|
||
- **替换外部依赖**:Tauri 命令使用 `SqliteStorage` 而非 Python 进程
|
||
- **无需 LanceDB**:现有 TF-IDF 方案已足够
|
||
|
||
## 二、简化方案
|
||
|
||
### 2.1 核心改动
|
||
|
||
| 改动 | 工作量 | 说明 |
|
||
|------|--------|------|
|
||
| 完善 `SqliteStorage` | 中 | 添加真正的 SQLite 持久化 |
|
||
| 集成 `SemanticScorer` | 小 | 替换简单的相似度计算 |
|
||
| 修改 `viking_commands.rs` | 中 | 使用 `SqliteStorage` 替代 Python 调用 |
|
||
| 删除 `viking_server.rs` | 小 | 不再需要服务器管理 |
|
||
|
||
### 2.2 架构对比
|
||
|
||
**当前架构** (需要外部 Python):
|
||
```
|
||
前端 → viking-client.ts → Tauri Commands → Python OpenViking 进程
|
||
```
|
||
|
||
**目标架构** (纯 Rust):
|
||
```
|
||
前端 → viking-client.ts → Tauri Commands → SqliteStorage (Rust)
|
||
→ SemanticScorer (TF-IDF)
|
||
→ ~/.zclaw/memories.db
|
||
```
|
||
|
||
## 三、架构设计
|
||
|
||
### 3.1 整体架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ ZCLAW Desktop (Tauri) │
|
||
│ │
|
||
│ ┌─────────────────┐ │
|
||
│ │ viking-client.ts│ (前端 API 保持不变) │
|
||
│ └────────┬────────┘ │
|
||
│ │ invoke() │
|
||
│ ┌────────▼────────────────────────────────────────────────────┐│
|
||
│ │ viking_commands.rs ││
|
||
│ │ (Tauri 命令层 - 接口不变,实现改为调用 zclaw-growth) ││
|
||
│ └────────┬────────────────────────────────────────────────────┘│
|
||
│ │ │
|
||
│ ┌────────▼────────────────────────────────────────────────────┐│
|
||
│ │ zclaw-growth (已存在) ││
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ ││
|
||
│ │ │SqliteStorage│ │SemanticScorer│ │ MemoryExtractor │ ││
|
||
│ │ │ (完善持久化)│ │ (TF-IDF) │ │ MemoryRetriever │ ││
|
||
│ │ └─────────────┘ └─────────────┘ │ PromptInjector │ ││
|
||
│ │ └─────────────────────┘ ││
|
||
│ └────────┬────────────────────────────────────────────────────┘│
|
||
│ │ │
|
||
│ ┌────────▼────────────────────────────────────────────────────┐│
|
||
│ │ 本地存储层 ││
|
||
│ │ ~/.zclaw/ ││
|
||
│ │ ├── memories.db (SQLite 持久化) ││
|
||
│ │ └── growth.json (成长指标) ││
|
||
│ └─────────────────────────────────────────────────────────────┘│
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 模块变更
|
||
|
||
| 模块 | 位置 | 变更 |
|
||
|------|------|------|
|
||
| `SqliteStorage` | `crates/zclaw-growth/src/storage/sqlite.rs` | **完善**:添加真正的 SQLite 持久化 |
|
||
| `viking_commands.rs` | `desktop/src-tauri/src/viking_commands.rs` | **修改**:使用 SqliteStorage |
|
||
| `viking_server.rs` | `desktop/src-tauri/src/viking_server.rs` | **删除**:不再需要 |
|
||
|
||
### 3.3 数据模型 (已存在)
|
||
|
||
```rust
|
||
// crates/zclaw-growth/src/types.rs
|
||
pub struct MemoryEntry {
|
||
pub uri: String, // agent://{agent_id}/{type}/{category}
|
||
pub memory_type: MemoryType,
|
||
pub content: String,
|
||
pub keywords: Vec<String>,
|
||
pub importance: u8, // 1-10
|
||
pub access_count: u32,
|
||
pub created_at: DateTime<Utc>,
|
||
pub last_accessed: DateTime<Utc>,
|
||
}
|
||
|
||
pub enum MemoryType {
|
||
Preference, // 用户偏好
|
||
Knowledge, // 知识积累
|
||
Experience, // 技能经验
|
||
Session, // 会话历史
|
||
}
|
||
```
|
||
|
||
## 四、接口设计
|
||
|
||
### 4.1 保持兼容的 Tauri 命令
|
||
|
||
| 命令 | 功能 | 变化 |
|
||
|------|------|------|
|
||
| `viking_status` | 检查状态 | 返回 `available: true` (始终可用) |
|
||
| `viking_add` | 添加资源 | 内部使用 SqliteStorage |
|
||
| `viking_find` | 语义搜索 | 使用 TF-IDF + SQLite FTS |
|
||
| `viking_grep` | 模式搜索 | 使用 SQLite FTS |
|
||
| `viking_ls` | 列出资源 | 从 SQLite 读取 |
|
||
| `viking_read` | 读取内容 | 从 SQLite 读取 |
|
||
| `viking_remove` | 删除资源 | 从 SQLite 删除 |
|
||
| `viking_tree` | 资源树 | 从 SQLite 构建 |
|
||
|
||
### 4.2 移除的命令
|
||
|
||
| 命令 | 原因 |
|
||
|------|------|
|
||
| `viking_server_start` | 无需服务器 |
|
||
| `viking_server_stop` | 无需服务器 |
|
||
| `viking_server_status` | 无需服务器 |
|
||
|
||
## 五、实施计划
|
||
|
||
### Phase 1: 完善 SqliteStorage (1-2 天)
|
||
|
||
**任务 1.1: 添加 sqlx 依赖**
|
||
```toml
|
||
# crates/zclaw-growth/Cargo.toml
|
||
[dependencies]
|
||
sqlx = { workspace = true, features = ["runtime-tokio", "sqlite"] }
|
||
```
|
||
|
||
**任务 1.2: 实现真正的 SQLite 持久化**
|
||
- 文件: `crates/zclaw-growth/src/storage/sqlite.rs`
|
||
- 改动:
|
||
```rust
|
||
pub struct SqliteStorage {
|
||
pool: SqlitePool, // 替换 RwLock<HashMap>
|
||
scorer: SemanticScorer, // 添加语义评分器
|
||
}
|
||
```
|
||
- 功能:
|
||
- `initialize_schema()` - 创建 memories 表和 FTS5 索引
|
||
- `store()` - 写入 SQLite
|
||
- `get()` - 从 SQLite 读取
|
||
- `find()` - 使用 SemanticScorer + FTS
|
||
|
||
**任务 1.3: 集成 SemanticScorer**
|
||
- 替换 `compute_similarity()` 简单实现
|
||
- 使用已有的 TF-IDF 算法
|
||
|
||
### Phase 2: 修改 Tauri 命令 (1 天)
|
||
|
||
**任务 2.1: 修改 viking_commands.rs**
|
||
```rust
|
||
// 替换
|
||
async fn viking_find(...) {
|
||
let cli = get_viking_cli_path()?;
|
||
let output = Command::new(&cli).arg("find")...
|
||
}
|
||
|
||
// 为
|
||
lazy_static! {
|
||
static ref STORAGE: SqliteStorage = ...;
|
||
}
|
||
|
||
async fn viking_find(...) {
|
||
STORAGE.find(query, options).await
|
||
}
|
||
```
|
||
|
||
**任务 2.2: 删除 viking_server.rs**
|
||
- 移除服务器管理相关命令
|
||
- 更新 `lib.rs` 移除模块引用
|
||
|
||
**任务 2.3: 初始化存储**
|
||
- 在 `lib.rs` 的 `run()` 函数中初始化 `SqliteStorage`
|
||
- 存储路径: `~/.zclaw/memories.db`
|
||
|
||
### Phase 3: 测试与验证 (1 天)
|
||
|
||
**任务 3.1: 单元测试**
|
||
- 完善 `SqliteStorage` 测试
|
||
- 测试持久化和恢复
|
||
|
||
**任务 3.2: 集成测试**
|
||
- 端到端测试: 前端 → Tauri → SqliteStorage
|
||
- 验证 `viking_find` 返回语义相关结果
|
||
|
||
**任务 3.3: 验收测试**
|
||
- 启动 Tauri 后无需配置即可使用
|
||
- 打包体积无显著增加
|
||
|
||
## 六、文件变更清单
|
||
|
||
### 修改文件
|
||
|
||
| 文件 | 变更 |
|
||
|------|------|
|
||
| `crates/zclaw-growth/src/storage/sqlite.rs` | 添加真正的 SQLite 持久化 |
|
||
| `crates/zclaw-growth/Cargo.toml` | 添加 sqlx 依赖 |
|
||
| `desktop/src-tauri/src/viking_commands.rs` | 使用 SqliteStorage |
|
||
| `desktop/src-tauri/src/lib.rs` | 移除 viking_server 模块,初始化存储 |
|
||
|
||
### 删除文件
|
||
|
||
| 文件 | 原因 |
|
||
|------|------|
|
||
| `desktop/src-tauri/src/viking_server.rs` | 不再需要服务器管理 |
|
||
|
||
### 保持不变
|
||
|
||
| 文件 | 原因 |
|
||
|------|------|
|
||
| `desktop/src/lib/viking-client.ts` | API 兼容 |
|
||
| `desktop/src/components/VikingPanel.tsx` | UI 不变 |
|
||
| `crates/zclaw-growth/src/viking_adapter.rs` | 接口不变 |
|
||
| `crates/zclaw-growth/src/retrieval/semantic.rs` | TF-IDF 已实现 |
|
||
|
||
## 七、风险与缓解
|
||
|
||
| 风险 | 影响 | 缓解措施 |
|
||
|------|------|----------|
|
||
| SQLite FTS5 中文支持 | 搜索质量 | 使用 `unicode61` tokenizer |
|
||
| TF-IDF 语义理解有限 | 搜索精度 | 可选:后续添加 embedding API |
|
||
| 数据迁移 | 用户数据丢失 | localStorage 降级保留 |
|
||
|
||
## 八、验收标准
|
||
|
||
- [ ] 启动 Tauri 后无需任何配置即可使用记忆功能
|
||
- [ ] `viking_status` 返回 `available: true`
|
||
- [ ] `viking_find` 返回语义相关结果(基于 TF-IDF)
|
||
- [ ] 数据持久化到 `~/.zclaw/memories.db`
|
||
- [ ] 打包体积无显著增加(< 1MB)
|
||
- [ ] 所有现有测试通过
|
||
- [ ] 前端 API (`viking-client.ts`) 无需修改
|
||
|
||
## 九、与现有设计文档的关系
|
||
|
||
本方案是对 `docs/superpowers/specs/2026-03-26-agent-growth-design.md` 的**简化实现**:
|
||
|
||
| 设计文档要求 | 本方案实现 |
|
||
|-------------|-----------|
|
||
| OpenViking 作为完整记忆层 | SqliteStorage (实现 VikingStorage trait) |
|
||
| 语义搜索 | TF-IDF (SemanticScorer) |
|
||
| L0/L1/L2 分层 | 已有实现,保持不变 |
|
||
| 记忆提取 | 已有 MemoryExtractor,保持不变 |
|
||
|
||
**核心差异**:设计文档说用 OpenViking Python 包,本方案用纯 Rust 实现替代,保持接口兼容。
|
||
|
||
## 十、对系统架构的影响分析
|
||
|
||
### 10.1 正面影响
|
||
|
||
| 影响 | 说明 |
|
||
|------|------|
|
||
| **消除外部依赖** | 不再需要 Python 环境 |
|
||
| **降低复杂度** | 移除进程管理代码 |
|
||
| **提高可靠性** | 无进程启动失败风险 |
|
||
| **减少打包体积** | 无需打包 Python |
|
||
|
||
### 10.2 潜在风险
|
||
|
||
| 风险 | 影响 | 缓解措施 |
|
||
|------|------|----------|
|
||
| TF-IDF 语义理解不如 embedding | 搜索精度降低 | 后续可选添加 embedding API |
|
||
| 大量记忆时性能下降 | 查询变慢 | 添加分页、索引优化 |
|
||
|
||
### 10.3 功能完整性
|
||
|
||
| 功能 | 原方案 (OpenViking) | 新方案 (SqliteStorage) |
|
||
|------|---------------------|------------------------|
|
||
| 存储记忆 | ✅ | ✅ |
|
||
| 语义搜索 | ✅ embedding | ⚠️ TF-IDF (可接受) |
|
||
| URI 寻址 | ✅ | ✅ |
|
||
| L0/L1/L2 分层 | ✅ | ✅ 已有实现 |
|
||
| 记忆提取 | ✅ | ✅ 已有实现 |
|
||
| 记忆检索 | ✅ | ✅ 已有实现 |
|
||
| Prompt 注入 | ✅ | ✅ 已有实现 |
|
||
|
||
### 10.4 结论
|
||
|
||
**推荐采用简化方案**:
|
||
1. 工作量小(3-4 天 vs 7+ 天)
|
||
2. 风险低(复用现有代码)
|
||
3. 满足"开箱即用"核心需求
|
||
4. 后续可渐进增强(添加 embedding)
|